﻿/* $RCSFile: CrmWrapper4.cs $
 * Apache license v2 2011 by Christian Surieux
 * $Source: ?/CRMWrapper3/CrmWrapper4.cs $
 * $log$
 * Revision 65 2011/02/22 01:23:08  christian.surieux
 *   V4 Migration 22/2/11
 * Revision 65 2011/02/22 01:22:23  christian.surieux
 *   V4 Migration 22/2/11
 * Revision 19 2011/01/21 17:51:08  christian.surieux
 *   Recover from Sony move files updated in 11/2010 were not in Source Control
 * Revision 6 2010/08/06 19:56:31  christian.surieux
 *   Added Log to All cs files
 */

using System;
using System.ComponentModel;
using System.Security.Principal;
using System.Diagnostics;
using System.Collections.Generic;
using System.IO;
using System.Xml.Serialization;
using System.Linq;
using System.Text;
using System.Net;
using System.Web;
using System.Web.Configuration;
using System.Web.Services.Protocols;
using System.Globalization;

using AddonNice.Settings;
using AddonNice.Settings.Cache;
using AddonNice.Security;

using AddonNice.CRMWrapper.CRM4ADDisco;
using AddonNice.CRMWrapper.CRM4Server;
using AddonNice.CRMWrapper.CRM4Meta;
using CrmSdk.CRM4;

using AddonNice.CRMWrapper.Authentication;

namespace AddonNice.CRMWrapper
{
	public  class Crm4WebService : CrmWebService
	{
		CrmService CrmServ4     =   null;

		#region published properties of CrmService
		public string Url
		{
			get
			{
				return CrmServ4.Url;
			}
			set
			{
				CrmServ4.Url	=	value;
			}
		}
		public bool PreAuthenticate
		{
			get
			{
				return CrmServ4.PreAuthenticate;
			}
			set
			{
				CrmServ4.PreAuthenticate    =	value;
			}
		}
		
		public ICredentials Credentials
		{
			get
			{
				return CrmServ4.Credentials;
			}
			set
			{
				CrmServ4.Credentials    =	value;
			}
		}
		public CRM4Server.CrmAuthenticationToken CrmAuthenticationTokenValue
		{
			get
			{
				return CrmServ4.CrmAuthenticationTokenValue;
			}
			set
			{
				CrmServ4.CrmAuthenticationTokenValue    =	value;
			}
		}

		#endregion published properties of CrmService

		#region Ctors
		
		/// <summary>
		/// Ctor for Online
		/// </summary>
		public Crm4WebService(string wurl,bool wpreauth,CRM4Server.CrmAuthenticationToken token,string OrganizationName)
		{
			if ( CRMTraceSwitch.Sw.TraceVerbose )
			{
				Trace.WriteLine( string.Format(CultureInfo.InvariantCulture,"[V]CRMWrapper4 Crm4WebService Ctor Url: {0}, preauthenticate: {1}, OrganizationName: {2}, authenticationType: Online",
					new object[] { wurl,wpreauth,OrganizationName }),CRMTraceSwitch.Sw.Info);
			}
			CrmServ4                                =   new CrmService();
			CrmServ4.Url                            =   wurl;
			CrmServ4.PreAuthenticate                =   wpreauth;
			// Set up the CRM Service.
			token.AuthenticationType                =   (int)ADNAuthenticationType.Online;
			token.OrganizationName                  =   OrganizationName;
			CrmServ4.CrmAuthenticationTokenValue    =   token;
		}

		/// <summary>
		/// Ctor for SPLA
		/// </summary>
		public Crm4WebService(string wurl,bool wpreauth,string ticket,string OrganizationName)
		{
			if ( CRMTraceSwitch.Sw.TraceVerbose )
			{
				Trace.WriteLine( string.Format(CultureInfo.InvariantCulture,"[V]CRMWrapper4 Crm4WebService Ctor Url: {0}, preauthenticate: {1}, OrganizationName: {2}, authenticationType: SPLA, ticket: '{3}'",
					new object[] { wurl,wpreauth,OrganizationName,ticket }),CRMTraceSwitch.Sw.Info);
			}
			CrmServ4                                =   new CrmService();
			CrmServ4.Url                            =   wurl;
			CrmServ4.PreAuthenticate                =   wpreauth;
			// Set up the CRM Service.
			CRM4Server.CrmAuthenticationToken token =   new CRM4Server.CrmAuthenticationToken();
			token.AuthenticationType                =   (int)ADNAuthenticationType.SPLA;
			token.OrganizationName                  =   OrganizationName;
			token.CrmTicket                         =   ticket;
			CrmServ4.CrmAuthenticationTokenValue    =   token;
		}

		/// <summary>
		/// Ctor for AD Crm mode nml
		/// </summary>
		public Crm4WebService(string wurl,bool wpreauth,ICredentials wicred,string OrganizationName)
		{
			if ( CRMTraceSwitch.Sw.TraceVerbose )
			{
				Trace.WriteLine( string.Format(CultureInfo.InvariantCulture,"[V]CRMWrapper4 Crm4WebService Ctor Url: {0}, preauthenticate: {1}, icredential: {2}, OrganizationName: {3}, authenticationType: AD",
					new object[] { wurl,wpreauth,wicred,OrganizationName }),CRMTraceSwitch.Sw.Info);
				try
				{
					NetworkCredential cred          =   wicred as NetworkCredential;
					if ( cred != null )
						Trace.WriteLine( string.Format(CultureInfo.InvariantCulture,"[V]CRMWrapper4 Crm4WebService Ctor cred.UserName: '{0}', cred.Domain: '{1}', cred.Password: '{2}'.",
							cred.UserName,cred.Domain,cred.Password),CRMTraceSwitch.Sw.Info);
				}
				catch(Exception ex) // not throwing in Ctor
				{
					Trace.WriteLine( string.Format(CultureInfo.InvariantCulture,"[E]CRMWrapper4 Crm4WebService Ctor NetworkCredential Pb ex: {0}",ex),CRMTraceSwitch.Sw.Info);
				}
			}
			CrmServ4                                =   new CrmService();
			CrmServ4.Url                            =   wurl;
			CrmServ4.PreAuthenticate                =   wpreauth;
			// Set up the CRM Service.
			CRM4Server.CrmAuthenticationToken token =   new CRM4Server.CrmAuthenticationToken();
			token.AuthenticationType                =   (int)ADNAuthenticationType.AD;
			token.OrganizationName                  =   OrganizationName;
			CrmServ4.Credentials                    =   wicred;
			CrmServ4.CrmAuthenticationTokenValue    =   token;
		}

		/// <summary>
		/// Ctor for AD Crm mode with impersonation
		/// </summary>
		public Crm4WebService(string wurl,bool wpreauth,ICredentials wicred,string OrganizationName,Guid adminUserId)
		{
			if ( CRMTraceSwitch.Sw.TraceVerbose )
				Trace.WriteLine( string.Format(CultureInfo.InvariantCulture,"[V]CRMWrapper4 Crm4WebService Ctor Url: {0}, preauthenticate: {1}, icredential: {2}, OrganizationName: {3}, authenticationType: AD, adminUserId: {4}",
					new object[]{wurl,wpreauth,wicred,OrganizationName,adminUserId}),CRMTraceSwitch.Sw.Info);
			CrmServ4                                =   new CrmService();
			CrmServ4.Url                            =   wurl;
			CrmServ4.PreAuthenticate                =   wpreauth;
			// we will use the callerId to impersonate on admin account
			CRM4Server.CrmAuthenticationToken token =   new CRM4Server.CrmAuthenticationToken();
			token.AuthenticationType                =   (int)ADNAuthenticationType.AD;
			token.OrganizationName                  =   OrganizationName;
			CrmServ4.Credentials                    =   wicred;
			token.CallerId                          =   adminUserId;
			CrmServ4.CrmAuthenticationTokenValue    =   token;
		}
		#endregion Ctors

		#region published methods of CrmService
		
		public override InternalResponse Execute(InternalRequest req)
		{
			return new InternalResponse(CrmServ4.Execute((CRM4Server.Request)req.Content));
		}

		public override void Update(InternalBusinessEntity be)
		{
			BusinessEntity e =   (BusinessEntity)be.Content;
			CrmServ4.Update(e);
		}
		
		public override void Delete(string typename, Guid Id)
		{
			CrmServ4.Delete(typename, Id);
		}
		
		public override InternalBusinessEntity Retrieve(string typename, Guid Id, InternalColumnSetBase col)
		{
			return new InternalBusinessEntity(CrmServ4.Retrieve(typename,Id,(ColumnSetBase)col));
		}
		
		public override InternalBusinessEntityCollection RetrieveMultiple(InternalQueryBase quer)
		{
			return new InternalBusinessEntityCollection(CrmServ4.RetrieveMultiple((QueryBase)quer));
		}
		
		public override Guid Create(InternalBusinessEntity be)
		{
			BusinessEntity e =   (BusinessEntity)be.Content;
			return CrmServ4.Create(e);
		}
		
		public override string Fetch(string fetch1)
		{
			return CrmServ4.Fetch(fetch1);
		}
		
		#endregion published methods of CrmService

		#region Raw methods which work directly with API for internal usage
		
		public CRM4Server.Response ExecuteRaw(CRM4Server.Request req)
		{
			return CrmServ4.Execute(req);
		}
		
		public void UpdateRaw(BusinessEntity be)
		{
			CrmServ4.Update(be);
		}
		
		public BusinessEntity RetrieveRaw(string typename, Guid Id,ColumnSetBase col)
		{
			return CrmServ4.Retrieve(typename,Id,col);
		}
		
		public BusinessEntityCollection RetrieveMultipleRaw(QueryBase quer)
		{
			return CrmServ4.RetrieveMultiple(quer);
		}
		
		public Guid CreateRaw(BusinessEntity be)
		{
			return CrmServ4.Create(be);
		}

		#endregion Raw methods which work directly with APIU

	}

	public class Crm4MetadataWebService: CrmMetadataWebService
	{
		MetadataService CrmMetaServ4                    =   null;

		#region published properties of MetadataService
		public string Url
		{
			get
			{
				return CrmMetaServ4.Url;
			}
			set
			{
				CrmMetaServ4.Url	=	value;
			}
		}
		public bool PreAuthenticate
		{
			get
			{
				return CrmMetaServ4.PreAuthenticate;
			}
			set
			{
				CrmMetaServ4.PreAuthenticate    =	value;
			}
		}
		
		public ICredentials Credentials
		{
			get
			{
				return CrmMetaServ4.Credentials;
			}
			set
			{
				CrmMetaServ4.Credentials    =	value;
			}
		}

		public CRM4Meta.CrmAuthenticationToken CrmAuthenticationTokenValue
		{
			get
			{
				return CrmMetaServ4.CrmAuthenticationTokenValue;
			}
			set
			{
				CrmMetaServ4.CrmAuthenticationTokenValue    =	value;
			}
		}
		#endregion published properties of MetadataService
		
		/// <summary>
		/// Ctor fo SPLA
		/// </summary>
		public Crm4MetadataWebService(string wurl,bool wpreauth,string ticket,string OrganizationName)
		{
			CrmMetaServ4                                =   new MetadataService();
			CrmMetaServ4.Url                            =   wurl;
			CrmMetaServ4.PreAuthenticate                =   wpreauth;
			CRM4Meta.CrmAuthenticationToken token       =   new CRM4Meta.CrmAuthenticationToken();
			token.AuthenticationType                    =   (int)ADNAuthenticationType.SPLA;
			token.OrganizationName                      =   OrganizationName;
			token.CrmTicket                             =   ticket;
			CrmMetaServ4.CrmAuthenticationTokenValue    =   token;
		}
		
		/// <summary>
		/// Ctor for AD
		/// </summary>
		public Crm4MetadataWebService(string wurl,bool wpreauth,ICredentials wicred,string OrganizationName)
		{
			CrmMetaServ4                                =   new MetadataService();
			CrmMetaServ4.Url                            =   wurl;
			CrmMetaServ4.PreAuthenticate                =   wpreauth;
			CRM4Meta.CrmAuthenticationToken token       =   new CRM4Meta.CrmAuthenticationToken();
			token.AuthenticationType                    =   (int)ADNAuthenticationType.AD;
			token.OrganizationName                      =   OrganizationName;
			CrmMetaServ4.Credentials                    =   wicred;
			CrmMetaServ4.CrmAuthenticationTokenValue    =   token;
		}

		static public MetadataItems ConvertMetaDataFlag(EntityInternalItems f)
		{
			MetadataItems fl  = 0;
			if (( f & EntityInternalItems.EntityOnly ) == EntityInternalItems.EntityOnly )
				fl |= MetadataItems.EntitiesOnly;
			if (( f & EntityInternalItems.IncludeAttributes ) == EntityInternalItems.IncludeAttributes )
				fl |= MetadataItems.IncludeAttributes;
			if (( f & EntityInternalItems.IncludePrivileges ) == EntityInternalItems.IncludePrivileges )
				fl |= MetadataItems.IncludePrivileges;
			if (( f & EntityInternalItems.IncludeRelationships ) == EntityInternalItems.IncludeRelationships )
				fl |= MetadataItems.IncludeRelationships;
			if (( f & EntityInternalItems.All ) == EntityInternalItems.All )
				fl |= MetadataItems.All;
			return fl;
		}

		#region published methods of MetadataService

		public override bool ExistEntityMetadata(string entityName)
		{
			CRM4Meta.RetrieveEntityRequest req  =   new RetrieveEntityRequest();
			req.LogicalName                     =   entityName;
			req.EntityItems                     =   EntityItems.EntityOnly;
			CRM4Meta.RetrieveEntityResponse ret =   (CRM4Meta.RetrieveEntityResponse)CrmMetaServ4.Execute(req);
			return (ret.EntityMetadata.SchemaName == entityName);
		}

		public override EntityInternalMetadata RetrieveEntityMetadata(string entityName, EntityInternalItems f)
		{
			CRM4Meta.RetrieveEntityRequest req  =   new RetrieveEntityRequest();
			req.LogicalName                     =   entityName;
			req.EntityItems                     =   (EntityItems)(int)f;
			CRM4Meta.RetrieveEntityResponse ret =   (CRM4Meta.RetrieveEntityResponse)CrmMetaServ4.Execute(req);
			return new EntityInternalMetadata(ret.EntityMetadata);
		}
		
		// object is RetrieveAllEntitiesResponse
		public override InternalMetadata RetrieveMetadata(EntityInternalItems f)
		{
			RetrieveAllEntitiesRequest request  =   new RetrieveAllEntitiesRequest();
			request.MetadataItems               =   (MetadataItems)(int)f;
			RetrieveAllEntitiesResponse ret     =   (RetrieveAllEntitiesResponse)CrmMetaServ4.Execute(request);
			return new InternalMetadata(ret.CrmMetadata);
		}
		public override InternalAttributeMetadata RetrieveAttributeMetadata(string entityName, string attributeName)
		{
			CRM4Meta.RetrieveAttributeRequest request   =   new RetrieveAttributeRequest();
			request.EntityLogicalName                   =   entityName;
			request.LogicalName                         =   attributeName;
			RetrieveAttributeResponse ret               =   (RetrieveAttributeResponse)CrmMetaServ4.Execute(request);
			return new InternalAttributeMetadata(ret.AttributeMetadata);
		}

		#endregion published methods of MetadataService

		#region raw methods working directly on API
		public CRM4Meta.MetadataServiceResponse ExecuteRaw(CRM4Meta.MetadataServiceRequest req)
		{
			return CrmMetaServ4.Execute(req);
		}
		
		public EntityMetadata RetrieveEntityMetadataRaw(string entityName, EntityItems f)
		{
			CRM4Meta.RetrieveEntityRequest req  =   new RetrieveEntityRequest();
			req.LogicalName                     =   entityName;
			req.EntityItems                     =   f;
			CRM4Meta.RetrieveEntityResponse ret =   (CRM4Meta.RetrieveEntityResponse)CrmMetaServ4.Execute(req);
			return ret.EntityMetadata;
		}
		
		// object is RetrieveAllEntitiesResponse
		public CRM4Meta.CrmMetadata[] RetrieveMetadataRaw(MetadataItems f)
		{
			RetrieveAllEntitiesRequest request  =   new RetrieveAllEntitiesRequest();
			request.MetadataItems               =   f;
			RetrieveAllEntitiesResponse ret     =   (RetrieveAllEntitiesResponse)CrmMetaServ4.Execute(request);
			return ret.CrmMetadata;
		}
		public AttributeMetadata RetrieveAttributeMetadataRaw(string entityName, string attributeName,bool RetrieveAsIfPublished)
		{
			CRM4Meta.RetrieveAttributeRequest request   =   new RetrieveAttributeRequest();
			request.EntityLogicalName                   =   entityName;
			request.LogicalName                         =   attributeName;
			request.RetrieveAsIfPublished               =   RetrieveAsIfPublished;
			RetrieveAttributeResponse ret               =   (RetrieveAttributeResponse)CrmMetaServ4.Execute(request);
			return ret.AttributeMetadata;
		}
		#endregion raw methods working directly on API
	}


	public class CrmWrapper4 : CRMWrapperBase
	{

		#region Services objects

		protected override CrmWebService userService
		{
			get
			{
			   return AuthenticationProvider.userService;
			}
		}

		protected override CrmWebService adminService
		{
			get
			{
				return AuthenticationProvider.adminService;
			}
		}

		protected override CrmWebService adminAdminService
		{
			get
			{
				return AuthenticationProvider.adminAdminService;
			}
		}

		public override CrmMetadataWebService userMetaService
		{
			get
			{
				return AuthenticationProvider.userMetaService;
			}
		}

		public override CrmMetadataWebService adminMetaService
		{
			get
			{
				return AuthenticationProvider.adminMetaService;
			}
		}

		Crm4WebService userService4
		{
			get
			{
				return AuthenticationProvider.userService4;
			}
		}

		Crm4WebService adminService4
		{
			get
			{
				return AuthenticationProvider.adminService4;
			}
		}

		Crm4WebService adminAdminService4
		{
			get
			{
				return AuthenticationProvider.adminAdminService4;
			}
		}

		Crm4MetadataWebService userMetaService4
		{
			get
			{
				return userMetaService as Crm4MetadataWebService;
			}
		}

		Crm4MetadataWebService adminMetaService4
		{
			get
			{
				return adminMetaService as Crm4MetadataWebService;
			}
		}

		#endregion services objects

		#region container for specialized CRM4 methods
		
		protected CRMUtil4 Util4
		{
			get
			{
				return Util as CRMUtil4;
			}
		}

		#endregion container for specialized CRM4 methods

		#region special properties override
		
		public override string DownloadServerUrl
		{
			get
			{
				if (_DownloadServerUrl == string.Empty)
				{
					string Url2         =   CrmServiceUrl.ToLower();
					int idx             =   Url2.IndexOf("/mscrmservices");
					_DownloadServerUrl  =   string.Format("{0}/{1}",Url2.Substring(0, idx),OrganizationName);
				}
				return _DownloadServerUrl;
			}
		}
		
		public override byte[] DownLoadFile(string url,ref bool OkDownload)
		{ 
			bool Ok     =   OkDownload;
			byte[] buf  =   AuthenticationProvider.DownLoadFile(url,ref Ok); 
			OkDownload  =   Ok;
			return buf;
		}

		public override string SqlAccessGroupName
		{
			get
			{
				return CurrentOrganization.sqlaccessgroupname;
			}
		}

		public override Guid SqlAccessGroupId
		{
			get
			{
				return CurrentOrganization.sqlaccessgroupid.Value;
			}
		}

		public override string ReportingGroupName
		{
			get
			{
				return CurrentOrganization.reportinggroupname;
			}
		}

		public override Guid ReportingGroupID
		{
			get
			{
				return CurrentOrganization.reportinggroupid.Value;
			}
		}

		public override Guid UserGroupId
		{
			get
			{
				return CurrentOrganization.usergroupid.Value;
			}
		}

		public override int LanguageCode
		{
			get
			{
				return CurrentOrganization.languagecode.Value;
			}
		}

		public override string CurrencySymbol
		{
			get
			{
				return CurrentOrganization.currencysymbol;
			}
		}

		public override Guid BaseCurrencyId 
		{
			get
			{
				return CurrentOrganization.basecurrencyid.Value;
			}
		}

		protected organization _CurrentOrganization             =   null;
		public organization CurrentOrganization
		{
			get
			{
				return _CurrentOrganization;
			}
			set
			{
				if ( value == null )
					return;
				_CurrentOrganization    =   value;
				_SchemaNamePrefix       =   value.schemanameprefix;
				_FullNameFormat         =   value.fullnameconventioncode.Value;
				_FullNameFormatName     =   value.fullnameconventioncode.name;
			}
		}
		#endregion special properties override

		#region discovery service main properties

		public override ADNAuthenticationType AuthenticationType
		{
			get 
			{
				if (_AuthenticationProvider == null)
					throw new Exception("Authentication Provider not set");
				if ( _AuthenticationProvider is AD )
						return ADNAuthenticationType.AD;
				if ( _AuthenticationProvider is SPLA )
						 return ADNAuthenticationType.SPLA;
				return ADNAuthenticationType.Online;
			}
			set 
			{
				if ( _AuthenticationProvider == null )
				{
					switch (value)
					{
						case ADNAuthenticationType.AD:
						_AuthenticationProvider     =   new AD(this);
						break;
						case ADNAuthenticationType.SPLA:
						_AuthenticationProvider     =   new SPLA(this);
						break;
						case ADNAuthenticationType.Online:
						_AuthenticationProvider     =   new Online(this);
						break;
					}
				}
			}
		}

		public CrmAuthenticationBase _AuthenticationProvider =   null;
		public CrmAuthenticationBase AuthenticationProvider
		{
			get
			{
				if (_AuthenticationProvider == null)
				{
					throw new Exception("Authentication Provider not set");
				}
				return _AuthenticationProvider;
			}
		}

		/// <summary>
		/// Admin CRM account
		/// </summary>
		protected override string CRMServiceAccount
		{ get{  return AuthenticationProvider.CRMServiceAccount;} set{ AuthenticationProvider.CRMServiceAccount=value;} }
		protected override string CRMServicePassword
		{ get{  return AuthenticationProvider.CRMServicePassword;} set{ AuthenticationProvider.CRMServicePassword=value;} }
		protected override string CRMServiceDomain
		{ get{  return AuthenticationProvider.CRMServiceDomain;} set{ AuthenticationProvider.CRMServiceDomain=value;} }

		/// <summary>
		/// Default eg anonymous CRM account
		/// </summary>
		protected override string CRMServiceDefaultAccount
		{ get{  return AuthenticationProvider.CRMServiceDefaultAccount;} set{ AuthenticationProvider.CRMServiceDefaultAccount=value;} }
		protected override string CRMServiceDefaultPassword
		{ get{  return AuthenticationProvider.CRMServiceDefaultPassword;} set{ AuthenticationProvider.CRMServiceDefaultPassword=value;} }
		protected override string CRMServiceDefaultDomain
		{ get{  return AuthenticationProvider.CRMServiceDefaultDomain;} set{ AuthenticationProvider.CRMServiceDefaultDomain=value;} }

		/// <summary>
		/// PrivateUser Group member
		/// </summary>
		protected override string CRMPrivAccount
		{ get{  return AuthenticationProvider.CRMPrivAccount;} set{ AuthenticationProvider.CRMPrivAccount=value;} }
		protected override string CRMPrivPassword
		{ get{  return AuthenticationProvider.CRMPrivPassword;} set{ AuthenticationProvider.CRMPrivPassword=value;} }
		protected override string CRMPrivDomain
		{ get{  return AuthenticationProvider.CRMPrivDomain;} set{ AuthenticationProvider.CRMPrivDomain=value;} }

		protected override string ServiceUrl
		{
			get
			{
				return AuthenticationProvider.ServiceUrl;
			}
			set
			{
				AuthenticationProvider.ServiceUrl    =   value;
			}
		}
		
		protected override string MetaDataServiceUrl
		{
			get
			{
				return AuthenticationProvider.MetaDataServiceUrl;
			}
			 set
			{
				AuthenticationProvider.MetaDataServiceUrl    =   value;
			}
	   }

		public OrganizationDetail Organization
		{
			get
			{
				return AuthenticationProvider.Organization;
			}
		}

		public int Port
		{
			get
			{
				return AuthenticationProvider.Port;
			}
			set
			{
				if ( value > 0 )
					AuthenticationProvider.Port   =   value;
			}
		}

		public string DiscoServerName
		{
			get
			{
				return AuthenticationProvider.DiscoServerName;
			}
			set
			{
				AuthenticationProvider.DiscoServerName =   value;
			}
		}
		
		protected override string WebApplicationUrl
		{
			get
			{
				return AuthenticationProvider.WebApplicationUrl;
			}
			set
			{
				AuthenticationProvider.WebApplicationUrl    =   value;
			}
		}

		public override string OrganizationName
		{
			get
			{
				return AuthenticationProvider.OrganizationName;
			}
			set
			{
				AuthenticationProvider.OrganizationName   =   value;
			}
		}

		public override string OrganizationFriendlyName
		{
			get
			{
				return AuthenticationProvider.OrganizationFriendlyName;
			}
			set
			{
				AuthenticationProvider.OrganizationFriendlyName   =   value;
			}
		}

		public override Guid OrganizationId
		{
			get
			{
				return AuthenticationProvider.OrganizationId;
			}
			set
			{
				AuthenticationProvider.OrganizationId    =   value;
			}
		}

		#endregion discovery service main properties

		#region version & organization

		public override string CrmVersion
		{
			get
			{
				RetrieveVersionRequest versionRequest   =   new RetrieveVersionRequest();
				RetrieveVersionResponse versionResponse =   null;
				try
				{
					versionResponse                     =   (RetrieveVersionResponse)adminAdminService4.ExecuteRaw(versionRequest);
				}
				catch (SoapException sx)
				{
					string msg                          =   string.Format("[E]CRMWrapper4 CrmVersion GET sex: {0}-{1}", sx, sx.Detail.InnerText);
					throw new CRMWrapperException(msg, sx);
				}
				catch (Exception ex)
				{
					string msg                          =   string.Format("[E]CRMWrapper4 CrmVersion GET ex: {0}", ex);
					if ( CRMTraceSwitch.Sw.TraceError )
						Trace.WriteLine( msg,CRMTraceSwitch.Sw.Info);
					throw new CRMWrapperException(msg, ex);
				}
				return versionResponse.Version.ToString();
			}
		}
		
		public bool FindOrganization(string orgName)
		{
			if ( CRMTraceSwitch.Sw.TraceVerbose )
				Trace.WriteLine( string.Format(CultureInfo.InvariantCulture,"[V]CRMWrapper4 FindOrganization BEG orgName: {0}.",orgName),CRMTraceSwitch.Sw.Info);
			return AuthenticationProvider.FindOrganization(orgName);
		}
		
		/// <summary>
		/// Retrieve with disco service list of all org managed on this CRM server
		/// </summary>
		public List<OrganizationDetail> Organizations
		{
			get
			{
				return AuthenticationProvider.Organizations;
			}
		}

		/// <summary>
		/// Sent by WrapperBase just after InitServices completion to get information about actual Organization admin settings
		/// </summary>
		protected override void ReadCurrentOrganization()
		{
			try
			{
				string ckey					        =   string.Format("CRM_CurrentOganization_{0}_{1}",Organization.OrganizationId,CrmVersion).Replace(' ','_').Replace(',','_');
				if ( CurrentCache.Exists(ckey))
				{
					CurrentOrganization		        =  (organization)CurrentCache.Get(ckey);
					if ( CRMTraceSwitch.Sw.TraceVerbose )
						Trace.WriteLine( string.Format(CultureInfo.InvariantCulture,"[V]CRMWrapper4 ReadCurrentOrganization found in cache CurrentOrganization: {0}, languagecode: {1}", _CurrentOrganization.name,_CurrentOrganization.languagecode.Value),CRMTraceSwitch.Sw.Info);
					return;
				}
				if ( CRMTraceSwitch.Sw.TraceVerbose )
					Trace.WriteLine( string.Format(CultureInfo.InvariantCulture,"[V]CRMWrapper4 ReadCurrentOrganization CurrentOrganizationId: {0}", Organization.OrganizationId),CRMTraceSwitch.Sw.Info);
				TargetRetrieveOrganization target   =   new TargetRetrieveOrganization();
				target.EntityId                     =   Organization.OrganizationId;

				RetrieveRequest req					=   new RetrieveRequest();
				req.ColumnSet						=   new AllColumns();
				req.Target							=   target;
				req.ReturnDynamicEntities			=   false;
				RetrieveResponse r					=   (RetrieveResponse)adminAdminService4.ExecuteRaw(req);
				if (r != null && r.BusinessEntity != null )
				{
					CurrentOrganization		        =   (organization)r.BusinessEntity;
					//insert in cache
					CurrentCache.InsertLong(ckey,CurrentOrganization);
					if ( CRMTraceSwitch.Sw.TraceVerbose )
						Trace.WriteLine( string.Format(CultureInfo.InvariantCulture,"[V]CRMWrapper4 ReadCurrentOrganization _CurrentOrganization: {0}, languagecode: {1}", _CurrentOrganization.name,_CurrentOrganization.languagecode.Value),CRMTraceSwitch.Sw.Info);
					return;
				}
			}
			catch (SoapException sx)
			{
				string msg  =   string.Format("[E]CRMWrapper4 ReadCurrentOrganization ex: {0}-{1}", sx, sx.Detail.InnerText);
				if ( CRMTraceSwitch.Sw.TraceError )
					Trace.WriteLine( msg,CRMTraceSwitch.Sw.Info);
				throw new CRMWrapperException(msg, sx);
			}
			catch (CRMWrapperException)
			{
				throw;
			}
			catch (Exception ex)
			{
				string msg  =   string.Format("[E]CRMWrapper4 ReadCurrentOrganization ex: {0}", ex);
				if ( CRMTraceSwitch.Sw.TraceError )
					Trace.WriteLine( msg,CRMTraceSwitch.Sw.Info);
				throw new CRMWrapperException(msg, ex);
			}
			const string msg0  =   "[E]CRMWrapper4  ReadCurrentOrganization failed throwing Exception";
			if ( CRMTraceSwitch.Sw.TraceError )
				Trace.WriteLine(msg0,CRMTraceSwitch.Sw.Info);
			throw new CRMWrapperException(msg0);
		}

		#endregion version & organization


		public CrmWrapper4(string organization,string wdiscoServerName, int wport,ADNAuthenticationType authTp,
			string CRMServiceAccount,string CRMServicePassword,string CRMServiceDomain,
			string CRMDefaultAccount,string CRMDefaultAccountPwd,string CRMDefaultAccountDn, 
			string CRMPrivAccount,string CRMPrivPassword,string CRMPrivDomain,bool UsePreAuthenticate)
			: base(CRMServiceAccount,CRMServicePassword,CRMServiceDomain,
					CRMDefaultAccount, CRMDefaultAccountPwd, CRMDefaultAccountDn, 
					CRMPrivAccount,CRMPrivPassword,CRMPrivDomain, authTp)
		{ 
			if ( CRMTraceSwitch.Sw.TraceVerbose )
				Trace.WriteLine( string.Format(CultureInfo.InvariantCulture,"[V]CRMWrapper4 Ctor BEG Organization: {0}, DiscoServer: {1}, Port: {2}, auth.Type: {3}",
					new object[]{organization,wdiscoServerName,wport,authTp}),CRMTraceSwitch.Sw.Info);
			DiscoServerName         =   wdiscoServerName;
			Port                    =   wport;
			if ( !FindOrganization(organization) )
			{
				string msg          =   string.Format("[E]CRMWrapper4 Organization: [{0}] not found on Server: [{1}] Port: [{2}]",
					organization,wdiscoServerName,wport);
				if ( CRMTraceSwitch.Sw.TraceError )
					Trace.WriteLine( msg,CRMTraceSwitch.Sw.Info);
				throw new CRMWrapperException(msg);
				}
			Util                    =   new CRMUtil4(this);
			// Create the admin services
			InitAdminService(UsePreAuthenticate);
			// Dispatch a Constructed event to all requesting objects
			CrmWrapperEventArgs ev  =   new CrmWrapperEventArgs(this,wrapperEventType.Constructed);
			OnCrmWrapperEvent(ev);
		}

		/// <summary>
		/// Current user name
		/// </summary>
		public override string userName
		{
			get
			{
				return AuthenticationProvider.userName;
			}
		}

		/// <summary>
		/// BusinessUnit of current user
		/// </summary>
		public override Guid businessUnitId
		{
			get
			{
				return sysUser.businessunitid;
			}
		}


		/// <summary>
		/// SystemUser corresponding to the authentified user
		/// </summary>
		ADNDynSystemUser sysUser
		{
			get
			{
				return AuthenticationProvider.sysUser;
			}
			set
			{
				AuthenticationProvider.sysUser	=	value;
				// we should have a dynamic typeCode here
				if ( CRMTraceSwitch.Sw.TraceVerbose )
					Trace.WriteLine( string.Format(CultureInfo.InvariantCulture,"[V]CRMWrapper4 sysUser set fullname: {0}", sysUser.fullname),CRMTraceSwitch.Sw.Info);
			}
		}

		/// <summary>
		/// The Guid corresponding to the authentified user, obtained with whoAmI using userService
		/// </summary>
		public override Guid userId
		{
			get
			{
				return AuthenticationProvider.userId;
			}
			set
			{
				AuthenticationProvider.userId   =   value;
				if ( CRMTraceSwitch.Sw.TraceVerbose )
					Trace.WriteLine( string.Format(CultureInfo.InvariantCulture,"[V]CRMWrapper4 userId SET: {0}", value),CRMTraceSwitch.Sw.Info);
			}
		}

		/// <summary>
		/// Domain name for the admin account
		/// </summary>
		public override string adminUserName
		{
			get
			{
				return AuthenticationProvider.adminUserName;
			}
		}
		
		protected ADNDynSystemUser InitAdminUser()
		{
			return AuthenticationProvider.InitAdminUser();
		}
		
		/// <summary>
		/// Guid of CRM administrator specified in config file
		/// </summary>
		public override Guid adminUserId
		{
			get
			{
				return AuthenticationProvider.adminUserId;
			}
		}

		public override bool IsUserOk4Crm(string domain,string login,string pwd)
		{
			if ( CRMTraceSwitch.Sw.TraceVerbose )
				Trace.WriteLine( "[V]CRMWrapper4 IsUserOk4Crm BEG.",CRMTraceSwitch.Sw.Info);
			bool ret                            =   AuthenticationProvider.IsUserOk4Crm(domain,login,pwd);
			if ( CRMTraceSwitch.Sw.TraceVerbose )
				Trace.WriteLine( string.Format(CultureInfo.InvariantCulture,"[V]CRMWrapper4 IsUserOk4Crm END: {0}",ret),CRMTraceSwitch.Sw.Info);
			return ret;       
		}

		/// <summary>
		/// Called by Ctor to create Admin crmservice objects necessary to first Crm calls with admin mode
		/// </summary>
		protected override void InitAdminService(bool UsePreAuthenticate)
		{
			if ( CRMTraceSwitch.Sw.TraceVerbose )
				Trace.WriteLine( "[V]CRMWrapper4 InitAdminService BEG.",CRMTraceSwitch.Sw.Info);

			AuthenticationProvider.InitAdminService(UsePreAuthenticate);
			_isAdminInitialized                             =   true;
			// We need this to call wrapper only after Application_AuthenticateRequest has run
			// if Application_AuthenticateRequest is not runned we can get the Http.Context.Current.User and never reach this point
			 if ( CRMTraceSwitch.Sw.TraceVerbose )
				 Trace.WriteLine( "[V]CRMWrapper4 InitAdminService END Ok",CRMTraceSwitch.Sw.Info);
		}
		
		/// <summary>
		/// Called by startWrapper to create different crmservice objects necessary to further running
		/// </summary>
		protected override void InitServices(bool UsePreAuthenticate)
		{
			if ( CRMTraceSwitch.Sw.TraceVerbose )
				Trace.WriteLine( "[V]CRMWrapper4 InitServices BEG.",CRMTraceSwitch.Sw.Info);
			AuthenticationProvider.InitServices(UsePreAuthenticate);
			_isInitialized      =   true;
			if ( CRMTraceSwitch.Sw.TraceVerbose )
				 Trace.WriteLine( "[V]CRMWrapper4 InitServices END Ok",CRMTraceSwitch.Sw.Info);
		}


		#region Create compound operations

		public override Guid userCreateCompound(InternalTargetCompound target)
		{
			if ( CRMTraceSwitch.Sw.TraceVerbose )
				Trace.WriteLine( string.Format(CultureInfo.InvariantCulture,"[V]CRMWrapper4 userCreateCompound TargetCompound Type: {0}", target),CRMTraceSwitch.Sw.Info);
			CompoundCreateRequest createReq =   new CompoundCreateRequest();
			createReq.Target                =   (TargetCompound)target.Content;
			CompoundCreateResponse cr       =   (CompoundCreateResponse)CreateRaw(createReq,false);
			return cr.Id;
		}

		public override Guid userCreateCompound(DynEntity entity,List<DynEntity> childs)
		{
			if ( CRMTraceSwitch.Sw.TraceVerbose )
				Trace.WriteLine( string.Format(CultureInfo.InvariantCulture,"[V]CRMWrapper4 userCreateCompound TargetCompound entity: {0}",entity.SchemaName),CRMTraceSwitch.Sw.Info);
			CompoundCreateRequest createReq =   new CompoundCreateRequest();
			createReq.Target                =   MakeTargetCompoundDynamicRaw(entity,childs);
			CompoundCreateResponse cr       =   (CompoundCreateResponse)CreateRaw(createReq,false);
			return cr.Id;
		}

		/// <summary>
		/// Dynamic create compound entity with the admin account
		/// </summary>
		public override Guid adminCreateCompound(InternalTargetCompound target)
		{
			if ( CRMTraceSwitch.Sw.TraceVerbose )
				Trace.WriteLine( string.Format(CultureInfo.InvariantCulture,"[V]CRMWrapper4 adminCreateCompound TargetCompound Type: {0}", target),CRMTraceSwitch.Sw.Info);
			CompoundCreateRequest createReq =   new CompoundCreateRequest();
			createReq.Target                =   (TargetCompound)target.Content;
			CompoundCreateResponse cr       =   (CompoundCreateResponse)CreateRaw(createReq,true);
			return cr.Id;
		}

		/// <summary>
		/// Dynamic create compound entity with the admin account
		/// </summary>
		public override Guid adminCreateCompound(DynEntity entity,List<DynEntity> childs)
		{
			if ( CRMTraceSwitch.Sw.TraceVerbose )
				Trace.WriteLine( string.Format(CultureInfo.InvariantCulture,"[V]CRMWrapper4 adminCreateCompound TargetCompound entity: {0}", entity.SchemaName),CRMTraceSwitch.Sw.Info);
			CompoundCreateRequest createReq =   new CompoundCreateRequest();
			createReq.Target                =   MakeTargetCompoundDynamicRaw(entity,childs);
			CompoundCreateResponse cr       =   (CompoundCreateResponse)CreateRaw(createReq,true);
			return cr.Id;
		}

		#endregion Create compound operations

		#region Rollup operations

		public override InternalResponse userRollup(string entityNm,Guid Id,InternalQueryBase quer,bool isDynamic)
		{
			if ( CRMTraceSwitch.Sw.TraceVerbose )
				Trace.WriteLine( string.Format(CultureInfo.InvariantCulture,"[V]CRMWrapper4 userRollup entity: {0}, Id: {1}, isDynamic: {2}", entityNm,Id,isDynamic),CRMTraceSwitch.Sw.Info);
			RollupResponse  bu                    =   RollupRaw(entityNm,Id,(QueryBase)quer,isDynamic,false);
			return new InternalResponse(bu);
		}

		public override InternalResponse userRollup(DynEntity entity,InternalQueryBase quer)
		{
			if ( CRMTraceSwitch.Sw.TraceVerbose )
				Trace.WriteLine( string.Format(CultureInfo.InvariantCulture,"[V]CRMWrapper4 userRollup dynEntity: {0}, Id: {1}", entity.SchemaName,entity.PrimaryKeyGuidValue),CRMTraceSwitch.Sw.Info);
			RollupResponse  bu                    =   RollupRaw(entity.SchemaName,entity.PrimaryKeyGuidValue,(QueryBase)quer,true,false);
			return new InternalResponse(bu);
		}

		/// <summary>
		/// Dynamic rollup entity with the admin account
		/// </summary>
		public override InternalResponse adminRollup(string entityNm,Guid Id,InternalQueryBase quer,bool isDynamic)
		{
			if ( CRMTraceSwitch.Sw.TraceVerbose )
				Trace.WriteLine( string.Format(CultureInfo.InvariantCulture,"[V]CRMWrapper4 adminRollup entity: {0}, Id: {1}, isDynamic: {2}", entityNm,Id,isDynamic),CRMTraceSwitch.Sw.Info);
			RollupResponse  bu                    =   RollupRaw(entityNm,Id,(QueryBase)quer,isDynamic,true);
			return new InternalResponse(bu);
		}

		/// <summary>
		/// Dynamic rollup entity with the admin account
		/// </summary>
		public override InternalResponse adminRollup(DynEntity entity,InternalQueryBase quer)
		{
			if ( CRMTraceSwitch.Sw.TraceVerbose )
				Trace.WriteLine( string.Format(CultureInfo.InvariantCulture,"[V]CRMWrapper4 adminRollup dynEntity: {0}, Id: {1}", entity.SchemaName,entity.PrimaryKeyGuidValue),CRMTraceSwitch.Sw.Info);
			RollupResponse  bu                =   RollupRaw(entity.SchemaName,entity.PrimaryKeyGuidValue,(QueryBase)quer,true,true);
			return new InternalResponse(bu);
		}

		public RollupResponse RollupRaw(string entityNm,Guid Id,QueryBase quer,bool isDynamic, bool admin)
		{
			if ( CRMTraceSwitch.Sw.TraceVerbose )
				Trace.WriteLine( string.Format(CultureInfo.InvariantCulture,"[V]CRMWrapper4 RollupRaw BEG entity: {0}, Id: {1}, isDynamic: {2}", entityNm,Id,isDynamic),CRMTraceSwitch.Sw.Info);

			RollupResponse rr               =   null;

			try
			{
				RollupRequest req               =   new RollupRequest();
				req.ReturnDynamicEntities       =   isDynamic;
				req.RollupType                  =   RollupType.Related;
				TargetRollupDynamic target      =   new TargetRollupDynamic();
				target.EntityName               =   entityNm;
				target.EntityId                 =   Id;
				target.Query                    =   quer;
				req.Target                      =   target;
				if (!admin)
						rr                      =   (RollupResponse)userService4.ExecuteRaw(req);
				else    rr                      =   (RollupResponse)adminService4.ExecuteRaw(req);
				BusinessEntityCollection bu     =   rr.BusinessEntityCollection;
				if ( CRMTraceSwitch.Sw.TraceVerbose )
					Trace.WriteLine( string.Format(CultureInfo.InvariantCulture,"[V]CRMWrapper4 RollupRaw END count: {0}", ((bu != null) && ( bu.BusinessEntities != null )) ? (bu.BusinessEntities.GetUpperBound(0)+1):0),CRMTraceSwitch.Sw.Info);
			}
			catch (SoapException sx)
			{
				string msg      =   string.Format("[E]CRMWrapper4 RollupRaw sex: {0}-{1}", sx, sx.Detail.InnerText);
				string errMsg   =   CRMUtil.GetErrorCode(sx);
				if ( errMsg == CrmStr.ObjectNotFound )
					msg         =   "[E]CRMWrapperBase RollupRaw Object not found exception.";
				if ( CRMTraceSwitch.Sw.TraceError )
					Trace.WriteLine( msg,CRMTraceSwitch.Sw.Info);
				if ( errMsg == CrmStr.ObjectNotFound )
					throw new CRMNotFoundException(msg, sx);
				throw new CRMWrapperException(msg, sx);
			}
			catch (Exception ex)
			{
				if ( CRMTraceSwitch.Sw.TraceError )
					Trace.WriteLine( string.Format(CultureInfo.InvariantCulture,"[E]CRMWrapper4 RollupRaw ex: {0}", ex),CRMTraceSwitch.Sw.Info);
				throw;
			}
			return rr;
		}

		#endregion Rollup operations

		#region Implementation for specific methods to avoid the encapsulation with Crmxxx objects

		public CRM4Server.Response userExecuteRaw(CRM4Server.Request r)
		{
			CRM4Server.Response rep    =   null;
			try
			{
				rep         =   userService4.ExecuteRaw(r);
			}
			catch (SoapException sx)
			{
				string msg      =   string.Format("[E]CRMWrapper4 userExecuteRaw sex: {0}-{1}", sx, sx.Detail.InnerText);
				string errMsg   =   CRMUtil.GetErrorCode(sx);
				if ( errMsg == CrmStr.ObjectNotFound )
					msg         =   "[E]CRMWrapperBase userExecuteRaw Object not found exception.";
				if ( CRMTraceSwitch.Sw.TraceError )
					Trace.WriteLine( msg,CRMTraceSwitch.Sw.Info);
				if ( errMsg == CrmStr.ObjectNotFound )
					throw new CRMNotFoundException(msg, sx);
				throw new CRMWrapperException(msg, sx);
			}
			catch (Exception ex)
			{
				if ( CRMTraceSwitch.Sw.TraceError )
					Trace.WriteLine( string.Format(CultureInfo.InvariantCulture,"[E]CRMWrapper4 userExecuteRaw ex: {0}", ex),CRMTraceSwitch.Sw.Info);
				throw;
			}
			return rep;
		}

		public CRM4Server.Response userUpdateRaw(UpdateRequest r)
		{
			CRM4Server.Response rep    =   null;
			try
			{
				rep                     =   userService4.ExecuteRaw(r);
			}
			catch (SoapException sx)
			{
				string msg      =   string.Format("[E]CRMWrapper4 userUpdateRaw sex: {0}-{1}", sx, sx.Detail.InnerText);
				string errMsg   =   CRMUtil.GetErrorCode(sx);
				if ( errMsg == CrmStr.ObjectNotFound )
					msg         =   "[E]CRMWrapperBase userUpdateRaw Object not found exception.";
				if ( CRMTraceSwitch.Sw.TraceError )
					Trace.WriteLine( msg,CRMTraceSwitch.Sw.Info);
				if ( errMsg == CrmStr.ObjectNotFound )
					throw new CRMNotFoundException(msg, sx);
				throw new CRMWrapperException(msg, sx);
			}
			catch (Exception ex)
			{
				if ( CRMTraceSwitch.Sw.TraceError )
					Trace.WriteLine( string.Format(CultureInfo.InvariantCulture,"[E]CRMWrapper4 userUpdate ex: {0}", ex),CRMTraceSwitch.Sw.Info);
				throw;
			}
			return rep;
		}

		public CRM4Server.Response CreateRaw(CRM4Server.Request create,bool isAdmin)
		{
			CRM4Server.Response rep = null;
			try
			{
				if ( isAdmin) 
					rep = adminService4.ExecuteRaw(create);
				else 
					rep = userService4.ExecuteRaw(create);
			}
			catch (SoapException sx)
			{
				if ( CRMTraceSwitch.Sw.TraceError )
					Trace.WriteLine( string.Format(CultureInfo.InvariantCulture,"[E]CRMWrapper4 Create isAdmin: {0}, ex: {1}-{2}",isAdmin,sx, sx.Detail.InnerText),CRMTraceSwitch.Sw.Info);
				throw new CRMWrapperException("userCreate soap: " + sx.Detail.InnerText, sx);
			}
			catch (Exception ex)
			{
				if ( CRMTraceSwitch.Sw.TraceError )
					Trace.WriteLine( string.Format(CultureInfo.InvariantCulture,"[E]CRMWrapper4 Create isAdmin: {0}, ex: {1}",isAdmin,ex),CRMTraceSwitch.Sw.Info);
				throw;
			}
			return rep;
		}

		public CRM4Server.Response userDeleteRaw(CRM4Server.Request delete)
		{
			CRM4Server.Response rep = null;
			try
			{
				rep = userService4.ExecuteRaw(delete);
			}
			catch (SoapException sx)
			{
				string msg      =   string.Format("[E]CRMWrapper4 userDeleteRaw sex: {0}-{1}", sx, sx.Detail.InnerText);
				string errMsg   =   CRMUtil.GetErrorCode(sx);
				if ( errMsg == CrmStr.ObjectNotFound )
					msg         =   "[E]CRMWrapperBase userDeleteRaw Object not found exception.";
				if ( CRMTraceSwitch.Sw.TraceError )
					Trace.WriteLine( msg,CRMTraceSwitch.Sw.Info);
				if ( errMsg == CrmStr.ObjectNotFound )
					throw new CRMNotFoundException(msg, sx);
				throw new CRMWrapperException(msg, sx);
			}
			catch (CRMWrapperException)
			{
				throw;
			}
			catch (Exception ex)
			{
				if ( CRMTraceSwitch.Sw.TraceError )
					Trace.WriteLine( string.Format(CultureInfo.InvariantCulture,"[E]CRMWrapper4 userDelete ex: {0}", ex),CRMTraceSwitch.Sw.Info);
				throw new CRMWrapperException("userDelete ex", ex);
			}
			return rep;
		}

		public CRM4Server.Response adminExecuteRaw(CRM4Server.Request r)
		{
			CRM4Server.Response rep    =   null;
			try
			{
				rep             =   adminService4.ExecuteRaw(r);
			}
			catch (SoapException sx)
			{
				string msg      =   string.Format("[E]CRMWrapper4 AdminExecuteRaw sex: {0}-{1}", sx, sx.Detail.InnerText);
				string errMsg   =   CRMUtil.GetErrorCode(sx);
				if ( errMsg == CrmStr.ObjectNotFound )
					msg         =   "[E]CRMWrapperBase AdminExecuteRaw Object not found exception.";
				if ( CRMTraceSwitch.Sw.TraceError )
					Trace.WriteLine( msg,CRMTraceSwitch.Sw.Info);
				if ( errMsg == CrmStr.ObjectNotFound )
					throw new CRMNotFoundException(msg, sx);
				throw new CRMWrapperException(msg, sx);
			}
			catch (CRMWrapperException)
			{
				throw;
			}
			catch (Exception ex)
			{
				if ( CRMTraceSwitch.Sw.TraceError )
					Trace.WriteLine( string.Format(CultureInfo.InvariantCulture,"[E]CRMWrapper4 AdminExecuteRaw ex: {0}", ex),CRMTraceSwitch.Sw.Info);
				throw new CRMWrapperException("adminExecute ex", ex);
			}
			return rep;
		}

		public MetadataServiceResponse adminMetaExecuteRaw(MetadataServiceRequest r)
		{
			if ( CRMTraceSwitch.Sw.TraceVerbose )
				Trace.WriteLine( string.Format(CultureInfo.InvariantCulture,"[V]CRMWrapper4 adminMetaExecuteRaw BEG Request: {0}", r),CRMTraceSwitch.Sw.Info);
			MetadataServiceResponse rep = null;
			try
			{
					rep = adminMetaService4.ExecuteRaw(r);
			}
			catch (SoapException sx)
			{
				string msg      =   string.Format("[E]CRMWrapper4 adminMetaExecuteRaw sex: {0}-{1}", sx, sx.Detail.InnerText);
				string errMsg   =   CRMUtil.GetErrorCode(sx);
				if ( errMsg == CrmStr.ObjectNotFound )
					msg         =   "[E]CRMWrapperBase adminMetaExecuteRaw Object not found exception.";
				if ( CRMTraceSwitch.Sw.TraceError )
					Trace.WriteLine( msg,CRMTraceSwitch.Sw.Info);
				if ( errMsg == CrmStr.ObjectNotFound )
					throw new CRMNotFoundException(msg, sx);
				throw new CRMWrapperException(msg, sx);
			}
			catch (Exception ex)
			{
				if ( CRMTraceSwitch.Sw.TraceError )
					Trace.WriteLine( string.Format(CultureInfo.InvariantCulture,"[E]CRMWrapper4 adminMetaExecuteRaw ex: {0}", ex),CRMTraceSwitch.Sw.Info);
				throw new CRMWrapperException("adminMetaExecuteRaw ex", ex);
			}
			return rep;
		}

		public CRM4Server.Response adminAdminExecuteRaw(CRM4Server.Request r)
		{
			if ( CRMTraceSwitch.Sw.TraceVerbose )
				Trace.WriteLine( string.Format(CultureInfo.InvariantCulture,"[V]CRMWrapper4 adminAdminExecuteRaw BEG Request: {0}", r),CRMTraceSwitch.Sw.Info);
			CRM4Server.Response rep = null;
			try
			{
					rep = adminAdminService4.ExecuteRaw(r);
			}
			catch (SoapException sx)
			{
				string msg      =   string.Format("[E]CRMWrapper4 adminAdminExecuteRaw sex: {0}-{1}", sx, sx.Detail.InnerText);
				string errMsg   =   CRMUtil.GetErrorCode(sx);
				if ( errMsg == CrmStr.ObjectNotFound )
					msg         =   "[E]CRMWrapperBase adminAdminExecuteRaw Object not found exception.";
				if ( CRMTraceSwitch.Sw.TraceError )
					Trace.WriteLine( msg,CRMTraceSwitch.Sw.Info);
				if ( errMsg == CrmStr.ObjectNotFound )
					throw new CRMNotFoundException(msg, sx);
				throw new CRMWrapperException(msg, sx);
			}
			catch (Exception ex)
			{
				if ( CRMTraceSwitch.Sw.TraceError )
					Trace.WriteLine( string.Format(CultureInfo.InvariantCulture,"[E]CRMWrapper4 adminAdminExecuteRaw ex: {0}", ex),CRMTraceSwitch.Sw.Info);
				throw new CRMWrapperException("adminAdminExecute ex", ex);
			}
			return rep;
		}

		public void Update(BusinessEntity be, bool admin)
		{
			try
			{
				if (!admin)
						userService4.UpdateRaw(be);
				else    adminService4.UpdateRaw(be);
			}
			catch (SoapException sx)
			{
				string msg      =   string.Format("[E]CRMWrapper4 Update sex: {0}-{1}", sx, sx.Detail.InnerText);
				string errMsg   =   CRMUtil.GetErrorCode(sx);
				if ( errMsg == CrmStr.ObjectNotFound )
					msg         =   "[E]CRMWrapperBase Update Object not found exception.";
				if ( CRMTraceSwitch.Sw.TraceError )
					Trace.WriteLine( msg,CRMTraceSwitch.Sw.Info);
				if ( errMsg == CrmStr.ObjectNotFound )
					throw new CRMNotFoundException(msg, sx);
				throw new CRMWrapperException(msg, sx);
			}
			catch (Exception ex)
			{
				if ( CRMTraceSwitch.Sw.TraceError )
					Trace.WriteLine( string.Format(CultureInfo.InvariantCulture,"[E]CRMWrapper4 Update ex: {0}", ex),CRMTraceSwitch.Sw.Info);
				throw;
			}
		}

		public BusinessEntity RetrieveRaw(string typename,Guid Id,ColumnSetBase col,bool admin)
		{
			BusinessEntity bu = null;
			try
			{
				if (!admin)
					 bu     =   userService4.RetrieveRaw(typename, Id,col);
				else bu     =   adminService4.RetrieveRaw(typename,Id,col);
			}
			catch (SoapException sx)
			{
				string msg      =   string.Format("[E]CRMWrapper4 RetrieveRaw sex: {0}-{1}", sx, sx.Detail.InnerText);
				string errMsg   =   CRMUtil.GetErrorCode(sx);
				if ( errMsg == CrmStr.ObjectNotFound )
					msg         =   "[E]CRMWrapperBase RetrieveRaw Object not found exception.";
				if ( CRMTraceSwitch.Sw.TraceError )
					Trace.WriteLine( msg,CRMTraceSwitch.Sw.Info);
				if ( errMsg == CrmStr.ObjectNotFound )
					throw new CRMNotFoundException(msg, sx);
				throw new CRMWrapperException(msg, sx);
			}
			catch (Exception ex)
			{
				if ( CRMTraceSwitch.Sw.TraceError )
					Trace.WriteLine( string.Format(CultureInfo.InvariantCulture,"[E]CRMWrapper4 Retrieve ex: {0}", ex),CRMTraceSwitch.Sw.Info);
				throw;
			}
			return bu;
		}

		public BusinessEntityCollection RetrieveMultipleRaw(QueryBase quer, bool admin)
		{
			BusinessEntityCollection bu = null;

			try
			{
				if (!admin)
						bu = userService4.RetrieveMultipleRaw(quer);
				else    bu = adminService4.RetrieveMultipleRaw(quer);
			}
			catch (SoapException sx)
			{
				string msg      =   string.Format("[E]CRMWrapper4 RetrieveMultipleRaw sex: {0}-{1}", sx, sx.Detail.InnerText);
				string errMsg   =   CRMUtil.GetErrorCode(sx);
				if ( errMsg == CrmStr.ObjectNotFound )
					msg         =   "[E]CRMWrapperBase RetrieveMultipleRaw Object not found exception.";
				if ( CRMTraceSwitch.Sw.TraceError )
					Trace.WriteLine( msg,CRMTraceSwitch.Sw.Info);
				if ( errMsg == CrmStr.ObjectNotFound )
					throw new CRMNotFoundException(msg, sx);
				throw new CRMWrapperException(msg, sx);
			}
			catch (Exception ex)
			{
				if ( CRMTraceSwitch.Sw.TraceError )
					Trace.WriteLine( string.Format(CultureInfo.InvariantCulture,"[E]CRMWrapper4 RetrieveMultiple ex: {0}", ex),CRMTraceSwitch.Sw.Info);
				throw;
			}
			return bu;
		}

		public Guid Create(BusinessEntity be,bool admin)
		{
			Guid wid = Guid.Empty;
			try
			{
				if ( !admin )
					wid = userService4.CreateRaw(be);
				else
					wid = adminService4.CreateRaw(be);
			}
			catch (SoapException sx)
			{
				if ( CRMTraceSwitch.Sw.TraceError )
					Trace.WriteLine( string.Format(CultureInfo.InvariantCulture,"[E]CRMWrapper4 Create ex: {0}-{1}", sx, sx.Detail.InnerText),CRMTraceSwitch.Sw.Info);
				throw new CRMWrapperException("Create soap: " + sx.Detail.InnerText, sx);
			}
			catch (Exception ex)
			{
				if ( CRMTraceSwitch.Sw.TraceError )
					Trace.WriteLine( string.Format(CultureInfo.InvariantCulture,"[E]CRMWrapper4 Create ex: {0}", ex),CRMTraceSwitch.Sw.Info);
				throw;
			}
			return wid;
		}

		public CRM4Meta.EntityMetadata internalRetrieveEntityMetadataRaw(string entityName, EntityItems f, bool isAdmin)
		{
			if ( CRMTraceSwitch.Sw.TraceVerbose )
				Trace.WriteLine( string.Format(CultureInfo.InvariantCulture,"[V]CRMWrapper4 InternalRetrieveEntityMetadataRaw  entityName: {0}, EntityItems: {1}, isAdmin: {2}", entityName, f,isAdmin),CRMTraceSwitch.Sw.Info);
			try
			{
				if (isAdmin)
					return adminMetaService4.RetrieveEntityMetadataRaw(entityName, f);
				return userMetaService4.RetrieveEntityMetadataRaw(entityName, f);
			}
			catch (SoapException sx)
			{
				string msg      =   string.Format("[E]CRMWrapper4 internalRetrieveEntityMetadataRaw sex: {0}-{1}", sx, sx.Detail.InnerText);
				string errMsg   =   CRMUtil.GetErrorCode(sx);
				if ( errMsg == CrmStr.ObjectNotFound )
					msg         =   "[E]CRMWrapperBase internalRetrieveEntityMetadataRaw Object not found exception.";
				if ( CRMTraceSwitch.Sw.TraceError )
					Trace.WriteLine( msg,CRMTraceSwitch.Sw.Info);
				if ( errMsg == CrmStr.ObjectNotFound )
					throw new CRMNotFoundException(msg, sx);
				throw new CRMWrapperException(msg, sx);
			}
			catch (CRMWrapperException)
			{
				throw;
			}
			catch (Exception ex)
			{
				if ( CRMTraceSwitch.Sw.TraceError )
					Trace.WriteLine( string.Format(CultureInfo.InvariantCulture,"[E]CRMWrapper4 internalRetrieveEntityMetadataRaw ex: {0}", ex),CRMTraceSwitch.Sw.Info);
				throw new CRMWrapperException("RetrieveEntityMetadataRaw ex", ex);
			}
		}

		public AttributeMetadata internalRetrieveAttributeMetadataRaw(string entityName, string attributeName,bool RetrieveAsIfPublished,bool isAdmin)
		{
			if ( CRMTraceSwitch.Sw.TraceVerbose )
				Trace.WriteLine( string.Format(CultureInfo.InvariantCulture,"[V]CRMWrapper4 internalRetrieveAttributeMetadataRaw  entityName: {0}, attributeName: {1}, isAdmin: {2}", entityName,attributeName,isAdmin),CRMTraceSwitch.Sw.Info);
			try
			{
				if (isAdmin )
					return adminMetaService4.RetrieveAttributeMetadataRaw(entityName,attributeName,RetrieveAsIfPublished);
				return userMetaService4.RetrieveAttributeMetadataRaw(entityName,attributeName,RetrieveAsIfPublished);
			}
			catch (SoapException sx)
			{
				string msg      =   string.Format("[E]CRMWrapper4 internalRetrieveAttributeMetadataRaw sex: {0}-{1}", sx, sx.Detail.InnerText);
				string errMsg   =   CRMUtil.GetErrorCode(sx);
				if ( errMsg == CrmStr.ObjectNotFound )
					msg         =   "[E]CRMWrapperBase internalRetrieveAttributeMetadataRaw Object not found exception.";
				if ( CRMTraceSwitch.Sw.TraceError )
					Trace.WriteLine( msg,CRMTraceSwitch.Sw.Info);
				if ( errMsg == CrmStr.ObjectNotFound )
					throw new CRMNotFoundException(msg, sx);
				throw new CRMWrapperException(msg, sx);
			}
			catch (CRMWrapperException)
			{
				throw;
			}
			catch (Exception ex)
			{
				string msg  =   string.Format("[E]CRMWrapper4 internalRetrieveAttributeMetadataRaw ex: {0}", ex);
				if ( CRMTraceSwitch.Sw.TraceError )
					Trace.WriteLine( msg,CRMTraceSwitch.Sw.Info);
				throw new CRMWrapperException(msg, ex);
			}
		}

		#endregion Implementation specific methods
		
		#region Utilities
		
		
		public override InternalRetrieveMultipleRequest MakeRetrieveMultipleRequest(InternalQueryExpression query, bool isDynamic)
		{
			QueryExpression Query           =   (QueryExpression)query;
			if ( CRMTraceSwitch.Sw.TraceVerbose )
				Trace.WriteLine( string.Format(CultureInfo.InvariantCulture,"[V]CRMWrapper4 MakeRetrieveMultipleRequest Query entityName: {0}, cols: {1}, isDynamic: {2}",Query.EntityName,Query.ColumnSet,isDynamic),CRMTraceSwitch.Sw.Info);
			RetrieveMultipleRequest req     =   new RetrieveMultipleRequest();
			req.Query                       =   Query;
			req.ReturnDynamicEntities       =   isDynamic;
			return new InternalRetrieveMultipleRequest(req);
		}
		
		public override InternalTargetCompoundDynamic MakeTargetCompoundDynamic(InternalDynamicEntity entity,InternalDynamicEntity[] childs)
		{
			TargetCompoundDynamic target    =   new TargetCompoundDynamic();
			target.Entity                   =   (DynamicEntity)entity.Content;
			DynamicEntity[] ch              =   new DynamicEntity[childs.Length];
			for(int i=0; i < childs.Length; i++)
			{
				ch[i]                       =   (DynamicEntity)childs[i].Content;
			}
			target.ChildEntities            =   ch;
			return new InternalTargetCompoundDynamic(target);
		}

		public override InternalTargetCompoundDynamic MakeTargetCompoundDynamic(DynEntity entity,List<DynEntity> childs)
		{
			if ( CRMTraceSwitch.Sw.TraceVerbose )
				Trace.WriteLine( string.Format(CultureInfo.InvariantCulture,"[V]CRMWrapper4 MakeTargetCompoundDynamic BEG entity: {0}, count: {1}", entity.SchemaName,childs.Count),CRMTraceSwitch.Sw.Info);
			TargetCompoundDynamic target    =   MakeTargetCompoundDynamicRaw(entity,childs);
			return new InternalTargetCompoundDynamic(target);
		}

		public TargetCompoundDynamic MakeTargetCompoundDynamicRaw(DynEntity entity,List<DynEntity> childs)
		{
			if ( CRMTraceSwitch.Sw.TraceVerbose )
				Trace.WriteLine( string.Format(CultureInfo.InvariantCulture,"[V]CRMWrapper4 MakeTargetCompoundDynamicRaw BEG entity: {0}, count: {1}", entity.SchemaName,childs.Count),CRMTraceSwitch.Sw.Info);
			TargetCompoundDynamic target    =   new TargetCompoundDynamic();
			target.Entity                   =   ToDynamicEntityRaw(entity);
			DynamicEntity[] ch              =   new DynamicEntity[childs.Count];
			for(int i=0; i < childs.Count; i++)
			{
				ch[i]                       =   ToDynamicEntityRaw(childs[i]);
			}
			target.ChildEntities            =   ch;
			return target;
		}

		/// <summary>
		/// Find user by its name
		/// </summary>
		systemuser GetUserByDomainName(string name)
		{
			systemuser currentUser				=   null;
			try
			{
				QueryExpression qe				=   new QueryExpression();
				qe.EntityName					=   CrmStr.systemuser;
				qe.ColumnSet					=   new AllColumns();
				
				ConditionExpression ce			=   new ConditionExpression();
				ce.AttributeName				=   CrmStr.domainname;
				ce.Operator						=   ConditionOperator.Equal;
				ce.Values						=   new object[] { name };

				qe.Criteria						=   new FilterExpression();
				// Set the properties of the filter.
				qe.Criteria.FilterOperator		=   LogicalOperator.And;
				qe.Criteria.Conditions			=   new ConditionExpression[] { ce };

				// Create the Request Object
				RetrieveMultipleRequest retrievePrincipal = new RetrieveMultipleRequest();

				// Set the Request Object's Properties
				retrievePrincipal.Query			=   qe;

				// Execute the Request
				RetrieveMultipleResponse principalResponse = (RetrieveMultipleResponse)adminAdminExecuteRaw(retrievePrincipal);
				BusinessEntity[] bu				=   principalResponse.BusinessEntityCollection.BusinessEntities;
				int sz							=	bu.GetUpperBound(0);
				if ( sz >= 0)
				{
					currentUser					= (systemuser)bu[0];
					if ( CRMTraceSwitch.Sw.TraceVerbose )
						Trace.WriteLine( string.Format(CultureInfo.InvariantCulture,"[V]CRMWrapper4 GetUserByDomainName upper bound read: {0}, UserName : {1}, currentUser.domainname: '{2}'", sz,name, currentUser.domainname),CRMTraceSwitch.Sw.Info);
					return currentUser;
				}
			}
			catch (SoapException sx)
			{
				string msg  =   string.Format("[E]CRMWrapper4 GetUserByDomainName ex: {0}-{1}", sx, sx.Detail.InnerText);
				if ( CRMTraceSwitch.Sw.TraceError )
					Trace.WriteLine( msg,CRMTraceSwitch.Sw.Info);
				throw new CRMWrapperException(msg, sx);
			}
			catch (CRMWrapperException)
			{
				throw;
			}
			catch (Exception ex)
			{
				string msg  =   string.Format("[E]CRMWrapper4 GetUserByDomainName ex: {0}", ex);
				if ( CRMTraceSwitch.Sw.TraceError )
					Trace.WriteLine( msg,CRMTraceSwitch.Sw.Info);
				throw new CRMWrapperException(msg, ex);
			}
			if ( CRMTraceSwitch.Sw.TraceVerbose )
				Trace.WriteLine( string.Format(CultureInfo.InvariantCulture,"[V]CRMWrapper4 GetUserByDomainName UserName : {0}, currentUser null", name),CRMTraceSwitch.Sw.Info);
			return null;
		}

		/// <summary>
		/// Find user by its name
		/// </summary>
		public override ADNDynSystemUser GetUserByDomainName2(string name)
		{
			return AuthenticationProvider.GetUserByDomainName2(name);
		}

		/// <summary>
		/// Find user by its CRM Guid
		/// </summary>
		systemuser GetUserById(Guid uId)
		{
			if ( CRMTraceSwitch.Sw.TraceVerbose )
				Trace.WriteLine( string.Format(CultureInfo.InvariantCulture,"[V]CRMWrapper4 GetUserById BEG UserId : {0}", uId),CRMTraceSwitch.Sw.Info);
			systemuser currentUser					= null;
			try
			{
				AllColumns cols						= new AllColumns();
				TargetRetrieveSystemUser target		= new TargetRetrieveSystemUser();
				target.EntityId						= uId;
				RetrieveRequest retrieve			= new RetrieveRequest();
				retrieve.Target						= target;
				retrieve.ColumnSet					= cols;

				// Execute the request.
				RetrieveResponse retrieved			= (RetrieveResponse)adminAdminExecuteRaw(retrieve);				
				currentUser							= (systemuser)retrieved.BusinessEntity ;
				if ( CRMTraceSwitch.Sw.TraceVerbose )
					Trace.WriteLine( string.Format(CultureInfo.InvariantCulture,"[V]CRMWrapper4 GetUserById UserId : {0} - {1}", uId,currentUser.domainname),CRMTraceSwitch.Sw.Info);
			}
			catch (SoapException sx)
			{
				string msg                          =   string.Format("[E]CRMWrapper4 GetUserById ex: {0}-{1}", sx, sx.Detail.InnerText);
				if ( CRMTraceSwitch.Sw.TraceError )
					Trace.WriteLine( msg,CRMTraceSwitch.Sw.Info);
				throw new CRMWrapperException(msg, sx);
			}
			catch (CRMWrapperException)
			{
				throw;
			}
			catch (Exception ex)
			{
				string msg                          =   string.Format("[E]CRMWrapper4 GetUserById ex: {0}", ex);
				if ( CRMTraceSwitch.Sw.TraceError )
					Trace.WriteLine( msg,CRMTraceSwitch.Sw.Info);
				throw new CRMWrapperException(msg, ex);
			}
			return currentUser;
		}

		public override ADNDynSystemUser GetUserById2(Guid uId)
		{
			return AuthenticationProvider.GetUserById2(uId);
		}

		#endregion Utilities

		#region Permissions and Privileges related functions

		/// <summary>
		/// Retrieve all the privileges for the specified role
		/// </summary>
		RolePrivilege[] GetRolePrivileges(role wrole)
		{
			string ckey					= string.Format("GetRolePrivileges_{0}_{1}_{2}", userId, wrole,CrmVersion).Replace(' ','_').Replace(',','_');
			if (CurrentCache.Exists(ckey))
				return (RolePrivilege[])CurrentCache.Get(ckey);
			// Create the request.
			RetrieveRolePrivilegesRoleRequest retrieve = new RetrieveRolePrivilegesRoleRequest();
			retrieve.RoleId				= wrole.roleid.Value;
			RetrieveRolePrivilegesRoleResponse retrieved = null;
			// Execute the request.
			try
			{
				retrieved				= (RetrieveRolePrivilegesRoleResponse)adminAdminExecuteRaw(retrieve);
			}
			catch (CRMWrapperException wx)
			{
				if ( CRMTraceSwitch.Sw.TraceError )
					Trace.WriteLine( string.Format(CultureInfo.InvariantCulture,"[E]CRMWrapper4 GetRolePrivileges ex: {0}}", wx),CRMTraceSwitch.Sw.Info);
				throw;
			}
			catch (SoapException sx)
			{
				if ( CRMTraceSwitch.Sw.TraceError )
					Trace.WriteLine( string.Format(CultureInfo.InvariantCulture,"[E]CRMWrapper4 GetRolePrivileges ex: {0}-{1}", sx, sx.Detail.InnerText),CRMTraceSwitch.Sw.Info);
				throw;
			}
			catch (Exception ex)
			{
				if ( CRMTraceSwitch.Sw.TraceError )
					Trace.WriteLine( string.Format(CultureInfo.InvariantCulture,"[E]CRMWrapper4 GetRolePrivileges ex: {0}", ex),CRMTraceSwitch.Sw.Info);
				throw;
			}

			CurrentCache.InsertLong(ckey,retrieved.RolePrivileges);
			return retrieved.RolePrivileges;
		}

		/// <summary>
		/// Retrieve a privilege to get its name
		/// </summary>
		privilege GetPrivilege(Guid id)
		{
			privilege p							    =   null;
			try
			{
				TargetRetrievePrivilege target	    =   new TargetRetrievePrivilege();
				target.EntityId					    =   id;
				
				RetrieveRequest retrievePrivilege   = new RetrieveRequest();
				retrievePrivilege.ReturnDynamicEntities = false;
				retrievePrivilege.Target		    =   target;
				retrievePrivilege.ColumnSet		    =   new AllColumns();
				RetrieveResponse retrieved		    =   (RetrieveResponse)adminAdminExecuteRaw(retrievePrivilege);

				p                                   =   (privilege)retrieved.BusinessEntity;
			}
			catch (SoapException sx)
			{
				if ( CRMTraceSwitch.Sw.TraceError )
					Trace.WriteLine( string.Format(CultureInfo.InvariantCulture,"[E]CRMWrapper4 GetPrivilege [{0}] soapex: {1}-{2}", id, sx, sx.Detail.InnerText),CRMTraceSwitch.Sw.Info);
				throw;
			}
			catch (CRMWrapperException)
			{
				throw;
			}
			catch (Exception ex)
			{
				if ( CRMTraceSwitch.Sw.TraceError )
					Trace.WriteLine( string.Format(CultureInfo.InvariantCulture,"[E]CRMWrapper4 GetPrivilege [{0}] ex: {1}", id,ex),CRMTraceSwitch.Sw.Info);
				throw;
			}
			return p;
		}
		

		/// <summary>
		/// Retrieve all the CRM Privileges
		/// </summary>
		public override InternalBusinessEntityCollection GetAllPrivileges()
		{
			// Create the request.
			RetrievePrivilegeSetRequest retrieve = new RetrievePrivilegeSetRequest();
			
			try
			{
				RetrievePrivilegeSetResponse retrieved = (RetrievePrivilegeSetResponse)adminService4.ExecuteRaw(retrieve);
				return   new InternalBusinessEntityCollection(retrieved.BusinessEntityCollection);
			}
			catch (SoapException sx)
			{
				if ( CRMTraceSwitch.Sw.TraceError )
					Trace.WriteLine( string.Format(CultureInfo.InvariantCulture,"[E]CRMWrapper4 GetAllPrivileges ex: {0}-{1}", sx, sx.Detail.InnerText),CRMTraceSwitch.Sw.Info);
			}
			catch (CRMWrapperException wx)
			{
				if ( CRMTraceSwitch.Sw.TraceError )
					Trace.WriteLine( string.Format(CultureInfo.InvariantCulture,"[E]CRMWrapper4 GetAllPrivileges ex: {0}}", wx),CRMTraceSwitch.Sw.Info);
				throw;
			}
			catch (Exception ex)
			{
				if ( CRMTraceSwitch.Sw.TraceError )
					Trace.WriteLine( string.Format(CultureInfo.InvariantCulture,"[E]CRMWrapper4 GetAllPrivileges ex: {0}", ex),CRMTraceSwitch.Sw.Info);
			}
			return null;
		}

		/// <summary>
		/// Retrieve all the privileges for the entity
		/// </summary>
		/// <param name="entityName">Schema name of the entity</param>
		/// <returns>Privilege Array</returns>
		protected SecurityPrivilegeMetadata[] GetEntityPrivilegesRaw(string entityName)
		{
			if ( CRMTraceSwitch.Sw.TraceVerbose )
				Trace.WriteLine( string.Format(CultureInfo.InvariantCulture,"[V]CRMWrapper4 GetEntityPrivilegesRaw  entityName: {0}", entityName),CRMTraceSwitch.Sw.Info);
			try
			{
				string ckey                         = string.Format("GetEntityPrivilegesRaw_{0}",CrmVersion).Replace(' ','_').Replace(',','_');
				if (CurrentCache.Exists(ckey))
				{
					if ( CRMTraceSwitch.Sw.TraceVerbose )
						Trace.WriteLine( "[V]CRMWrapper4 GetEntityPrivilegesRaw found in cache.",CRMTraceSwitch.Sw.Info);
					return (SecurityPrivilegeMetadata[])CurrentCache.Get(ckey);
				}
				EntityMetadata entity   =   internalRetrieveEntityMetadataRaw(entityName, EntityItems.IncludePrivileges,true);
				SecurityPrivilegeMetadata[] priv      =   entity.Privileges;
				if ( priv.Length > 0 )
					CurrentCache.InsertLong(ckey, priv);
				if ( CRMTraceSwitch.Sw.TraceVerbose )
				{
					Trace.WriteLine( string.Format(CultureInfo.InvariantCulture,"[V]CRMWrapper4 GetEntityPrivilegesRaw  entityName: {0}, priv.Length: {1}",entityName,priv.Length),CRMTraceSwitch.Sw.Info);
					for (int i=0; i < priv.Length; i++ ) 
						Trace.WriteLine( string.Format(CultureInfo.InvariantCulture,"[V]CRMWrapper4 GetEntityPrivilegesRaw  i: {0}, name: {1}, PrivilegeType: {2}.",i,priv[i].Name,priv[i].PrivilegeType.Value),CRMTraceSwitch.Sw.Info);
				}
				return priv;              
			}
			catch (SoapException sx)
			{
				string msg  =   string.Format("[E]CRMWrapper4 GetEntityPrivilegesRaw sex: {0}-{1}", sx, sx.Detail.InnerText);
				if ( CRMTraceSwitch.Sw.TraceError )
					Trace.WriteLine(msg,CRMTraceSwitch.Sw.Info);
				throw new CRMWrapperException(msg, sx);
			}
			catch (CRMWrapperException)
			{
				throw;
			}
			catch (Exception ex)
			{
				string msg  =   string.Format("[E]CRMWrapper4 GetEntityPrivilegesRaw ex: {0}", ex);
				if ( CRMTraceSwitch.Sw.TraceError )
					Trace.WriteLine( msg,CRMTraceSwitch.Sw.Info);
				throw new CRMWrapperException(msg, ex);
			}
		}

		/// <summary>
		/// Retrieve all the Privileges for the connected user
		/// </summary>
		public override InternalRolePrivilegeArray GetUserPrivileges()
		{
			try
			{
				RetrieveUserPrivilegesRequest retrieve  =   new RetrieveUserPrivilegesRequest();
				retrieve.UserId                         =   userId;
				// Execute the request.
				RetrieveUserPrivilegesResponse retrieved =  (RetrieveUserPrivilegesResponse)adminAdminExecuteRaw(retrieve);
				return new InternalRolePrivilegeArray (retrieved.RolePrivileges);
			}
			catch (SoapException sx)
			{
				if ( CRMTraceSwitch.Sw.TraceError )
					Trace.WriteLine( string.Format(CultureInfo.InvariantCulture,"[E]CRMWrapper4 GetUserPrivileges ex: {0}-{1}", sx, sx.Detail.InnerText),CRMTraceSwitch.Sw.Info);
				throw new CRMWrapperException("GetUserPrivileges Sx", sx);
			}
			catch (CRMWrapperException wx)
			{
				if ( CRMTraceSwitch.Sw.TraceError )
					Trace.WriteLine( string.Format(CultureInfo.InvariantCulture,"[E]CRMWrapper4 GetUserPrivileges ex: {0}}", wx),CRMTraceSwitch.Sw.Info);
				throw;
			}
			catch (Exception ex)
			{
				if ( CRMTraceSwitch.Sw.TraceError )
					Trace.WriteLine( string.Format(CultureInfo.InvariantCulture,"[E]CRMWrapper4 GetUserPrivileges ex: {0}", ex),CRMTraceSwitch.Sw.Info);
				throw new CRMWrapperException("GetUserPrivileges ex", ex);
			}
		}

		/// <summary>
		/// Get the connected user's AccessRights for a specific occurence of an entity
		/// Insert it in cache to improve speed
		/// TDB set a dependency for this in the cache
		/// </summary>
		public override InternalCrmAccessRights  GetAccessRights(string EntName,Guid wGuid)
		{
			AccessRights r              =   AccessRights.ReadAccess;
			string ckey                 =   string.Format("GetAccessRights_{0}_{1}_{2}_{3}",
				new object[]{EntName, wGuid, userId,CrmVersion}).Replace(' ','_').Replace(',','_');
			if (CurrentCache.Exists(ckey))
				return (InternalCrmAccessRights)(int)(AccessRights)CurrentCache.Get(ckey);
			
			try
			{
				// Create the SecurityPrincipal object.
				// This class references the user whose access is being checked.
				SecurityPrincipal principal =   new SecurityPrincipal();

				// Set the properties of the SecurityPrincipal object.
				// Type is the typecode of the principalid.
				principal.Type = SecurityPrincipalType.User;
				// PrincipalId is the GUID of the user whose access is being checked.
				principal.PrincipalId       =   userId;

				// Create the target for the request.
				TargetOwnedDynamic owner    =   new TargetOwnedDynamic();
				owner.EntityName            =   EntName;
				// EntityId is the GUID of the account to which access is being checked.
				owner.EntityId              =   wGuid;

				// Create the request object.
				RetrievePrincipalAccessRequest access = new RetrievePrincipalAccessRequest();

				// Set the properties of the request object.
				access.Principal            =   principal;
				access.Target               =   owner;

				// Execute the request.
				RetrievePrincipalAccessResponse accessResponse = (RetrievePrincipalAccessResponse)adminService4.ExecuteRaw(access);
				r                           =   accessResponse.AccessRights;
				if ( CRMTraceSwitch.Sw.TraceVerbose )
					Trace.WriteLine( string.Format(CultureInfo.InvariantCulture,"[V]CRMWrapper4 GetAccesRights UserName : {0}, AccessRights : {1}",userName, r),CRMTraceSwitch.Sw.Info);
				CurrentCache.InsertLong(ckey, r);
			}
			catch (SoapException sx)
			{
				if ( CRMTraceSwitch.Sw.TraceError )
					Trace.WriteLine( string.Format(CultureInfo.InvariantCulture,"[E]CRMWrapper4 GetAccesRights  ex: {0}-{1}", sx, sx.Detail.InnerText),CRMTraceSwitch.Sw.Info);
				throw;
			}
			catch (CRMWrapperException wx)
			{
				if ( CRMTraceSwitch.Sw.TraceError )
					Trace.WriteLine( string.Format(CultureInfo.InvariantCulture,"[E]CRMWrapper4 GetAccesRights ex: {0}}", wx),CRMTraceSwitch.Sw.Info);
				throw;
			}
			catch (Exception ex)
			{
				if ( CRMTraceSwitch.Sw.TraceError )
					Trace.WriteLine( string.Format(CultureInfo.InvariantCulture,"[E]CRMWrapper4 GetAccesRights ex: {0}", ex),CRMTraceSwitch.Sw.Info);
				throw;
			}
			
		return (InternalCrmAccessRights)(int)r;
		}

		List<SecurityPrivilegeMetadata> GetEntityPrivilegesForRight(string EntName,PrivilegeType pType)
		{
			if ( CRMTraceSwitch.Sw.TraceVerbose )
				Trace.WriteLine( string.Format(CultureInfo.InvariantCulture,"[V]CRMWrapper4  GetEntityPrivilegesForRight BEG EntName: [{0}],  PrivilegeType: {1}", EntName,pType),CRMTraceSwitch.Sw.Info);
			SecurityPrivilegeMetadata[] entPriv     =   GetEntityPrivilegesRaw(EntName);
			List<SecurityPrivilegeMetadata> lst     =   new List<SecurityPrivilegeMetadata>();
			foreach ( SecurityPrivilegeMetadata sp in entPriv )
			{
				if ( sp.PrivilegeType.Value == pType )
				{
					lst.Add(sp);
					if ( CRMTraceSwitch.Sw.TraceVerbose )
						Trace.WriteLine( string.Format(CultureInfo.InvariantCulture,"[V]CRMWrapper4  GetEntityPrivilegesForRight found Name: {0}.", sp.Name),CRMTraceSwitch.Sw.Info);
				}
			}
			if ( CRMTraceSwitch.Sw.TraceVerbose )
				Trace.WriteLine( string.Format(CultureInfo.InvariantCulture,"[V]CRMWrapper4  GetEntityPrivilegesForRight END EntName: {0},  PrivilegeType: {1}, Count: {2}", EntName,pType,lst.Count),CRMTraceSwitch.Sw.Info);
			return lst;
		}

		bool CheckPrivilege(string EntName, PrivilegeType pType)
		{
			if ( CRMTraceSwitch.Sw.TraceVerbose )
				Trace.WriteLine( string.Format(CultureInfo.InvariantCulture,"[V]CRMWrapper4  CheckPrivilege BEG EntName: {0},  PrivilegeType: {1}", EntName,pType),CRMTraceSwitch.Sw.Info);
			List<SecurityPrivilegeMetadata> entPriv =   GetEntityPrivilegesForRight(EntName,pType);
			Dictionary<string,privilege> tbr        =   GetAllUserPrivileges();
			foreach ( SecurityPrivilegeMetadata sp in entPriv )
			{
				if ( !tbr.ContainsKey(sp.Name) )
				{
					if ( CRMTraceSwitch.Sw.TraceVerbose )
						Trace.WriteLine( string.Format(CultureInfo.InvariantCulture,"[V]CRMWrapper4  CheckPrivilege END EntName: {0},  NOT found Name: {1}",EntName,sp.Name),CRMTraceSwitch.Sw.Info);
					return false;
				}
			}
			if ( CRMTraceSwitch.Sw.TraceVerbose )
				Trace.WriteLine( string.Format(CultureInfo.InvariantCulture,"[V]CRMWrapper4  CheckPrivilege END OK EntName: {0}.",EntName),CRMTraceSwitch.Sw.Info);
			return true;
		}
				
		/// <summary>
		/// Has the current user rigths on this entity type
		/// </summary>
		public override bool HasPermissions(string EntName, ADNCRMRights r )
		{
			if ( CRMTraceSwitch.Sw.TraceVerbose )
				Trace.WriteLine( string.Format(CultureInfo.InvariantCulture,"[V]CRMWrapper4 HasPermissions EntName: [{0}],  ADNCRMRights: {1}", EntName,r),CRMTraceSwitch.Sw.Info);
			//AccessRights userRights;
			bool ok             = false;

			try
			{
				switch (r)
				{
					case ADNCRMRights.ReadAccess:
						ok          =   CheckPrivilege(EntName, PrivilegeType.Read);
					break;
					case ADNCRMRights.AddAccess:
						ok          =   CheckPrivilege(EntName, PrivilegeType.Create);
					break;
					case ADNCRMRights.WriteAccess:
						ok          =   CheckPrivilege(EntName, PrivilegeType.Write);
					break;
					case ADNCRMRights.DeleteAccess:
						ok          =   CheckPrivilege(EntName, PrivilegeType.Delete);
					break;

					case ADNCRMRights.EditAccess:
					case ADNCRMRights.AdminAccess:
						{
							string[] CRMRoles = GetStrUserRoles(userId);
							if ( CRMTraceSwitch.Sw.TraceVerbose )
								Trace.WriteLine( string.Format(CultureInfo.InvariantCulture,"[V]CRMWrapper4 HasPermissions EntName: {0},  ADNCRMRights: {1}, CRMRoles.Length: {2}, Config.CRMAdminRole :{3}", new object[] { EntName, r, CRMRoles.Length, Config.CRMAdminRole }),CRMTraceSwitch.Sw.Info);
							for (int i = 0; i < CRMRoles.Length; i++)
							{
								string str	=	CRMRoles[i];
								if ( CRMTraceSwitch.Sw.TraceVerbose )
									Trace.WriteLine( string.Format(CultureInfo.InvariantCulture,"[V]CRMWrapper4 HasPermissions EntName: {0},  ADNCRMRights: {1}, i: {2}, CRMRoles[i]: '{3}', Config.CRMAdminRole: '{4}'", new object[]{EntName,r,i,str,Config.CRMAdminRole}),CRMTraceSwitch.Sw.Info);
								if ( str == Config.CRMAdminRole )
								{
									ok = true;
									break;
								}
							}
							break;
						}
				}
			}
			catch (SoapException sx)
			{
				if ( CRMTraceSwitch.Sw.TraceError )
					Trace.WriteLine( string.Format(CultureInfo.InvariantCulture,"[E]CRMWrapper4 HasPermissions  SoapException : {0}-{1}", sx, sx.Detail.InnerText),CRMTraceSwitch.Sw.Info);
				throw;
			}
			catch (CRMWrapperException wx)
			{
				if ( CRMTraceSwitch.Sw.TraceError )
					Trace.WriteLine( string.Format(CultureInfo.InvariantCulture,"[E]CRMWrapper4 HasPermissions ex: {0}}", wx),CRMTraceSwitch.Sw.Info);
				throw;
			}
			catch (Exception ex)
			{
				if ( CRMTraceSwitch.Sw.TraceError )
					Trace.WriteLine( string.Format(CultureInfo.InvariantCulture,"[E]CRMWrapper4 HasPermissions ex: {0}", ex),CRMTraceSwitch.Sw.Info);
				throw;
			}
			if ( CRMTraceSwitch.Sw.TraceVerbose )
				Trace.WriteLine( string.Format(CultureInfo.InvariantCulture,"[V]CRMWrapper4 HasPermissions result: {2}, {4}-{3} ,typename : {0}, ADNCRMRights : {1}", new object[] { EntName, r, ok, userId,userName }),CRMTraceSwitch.Sw.Info);
			return ok;
		}
		

		/// <summary>
		/// Liste des Privileges de l'utilisateur sous forme d'un dictionnaire
		/// </summary>
		Dictionary<string, privilege> GetAllUserPrivileges()
		{
			string ckey                         = string.Format("GetAllUserPrivileges_{0}_{1}", userId, CrmVersion).Replace(' ','_').Replace(',','_');
			if (CurrentCache.Exists(ckey))
			{
				if ( CRMTraceSwitch.Sw.TraceVerbose )
					Trace.WriteLine( "[V]CRMWrapper4 GetAllUserPrivileges found in cache.",CRMTraceSwitch.Sw.Info);
				return (Dictionary<string, privilege> )CurrentCache.Get(ckey);
			}
			Dictionary<string, privilege> dicPriv   =   new Dictionary<string, privilege>();
			try
			{
				QueryExpression qe				    =   new QueryExpression();
				qe.EntityName					    =   CrmStr.privilege;
				qe.ColumnSet					    =   new AllColumns();

				LinkEntity le                       =   new LinkEntity();
				le.LinkFromEntityName			    =   CrmStr.privilege;
				le.LinkFromAttributeName		    =   CrmStr.privilegeid;
				le.LinkToEntityName				    =   CrmStr.roleprivileges;
				le.LinkToAttributeName			    =   CrmStr.privilegeid;

				LinkEntity le0					    =   new LinkEntity();
				le0.LinkFromEntityName			    =   CrmStr.roleprivileges;
				le0.LinkFromAttributeName		    =   CrmStr.roleid;
				le0.LinkToEntityName			    =   CrmStr.systemuserroles;
				le0.LinkToAttributeName			    =   CrmStr.roleid;

				LinkEntity le2					    =   new LinkEntity();
				le2.LinkFromEntityName			    =   CrmStr.systemuserroles;
				le2.LinkFromAttributeName		    =   CrmStr.systemuserid;
				le2.LinkToEntityName			    =   CrmStr.systemuser;
				le2.LinkToAttributeName			    =   CrmStr.systemuserid;

				ConditionExpression ce			    =   new ConditionExpression();
				ce.AttributeName				    =   CrmStr.systemuserid;
				ce.Operator						    =   ConditionOperator.Equal;
				ce.Values						    =   new object[] { userId };

				le2.LinkCriteria				    =   new FilterExpression();
				le2.LinkCriteria.Conditions		    =   new ConditionExpression[] { ce };

				le0.LinkEntities				    =   new LinkEntity[] { le2 };
				le.LinkEntities					    =   new LinkEntity[] { le0 };
				qe.LinkEntities					    =   new LinkEntity[] { le };

				// Create the Request Object
				RetrieveMultipleRequest retrievePrincipal = new RetrieveMultipleRequest();

				// Set the Request Object's Properties
				retrievePrincipal.Query			    =   qe;

				// Execute the Request
				RetrieveMultipleResponse principalResponse =    (RetrieveMultipleResponse)adminAdminExecuteRaw(retrievePrincipal);
				BusinessEntity[] bu				    =   principalResponse.BusinessEntityCollection.BusinessEntities;
				if ( CRMTraceSwitch.Sw.TraceVerbose )
					Trace.WriteLine( string.Format(CultureInfo.InvariantCulture,"[V]CRMWrapper4 GetAllUserPrivileges bu.Length: {0}", bu.Length),CRMTraceSwitch.Sw.Info);
				for (int i=0 ;  i < bu.Length ; i++ )
				{
					privilege p					    =   (privilege)bu[i];
					if ( CRMTraceSwitch.Sw.TraceVerbose )
						Trace.WriteLine( string.Format(CultureInfo.InvariantCulture,"[V]CRMWrapper4 GetAllUserPrivileges i: {0}, p.name: {1}", i, p.name),CRMTraceSwitch.Sw.Info);
					if (!dicPriv.ContainsKey(p.name))
					{
						dicPriv.Add(p.name, p);
						if ( CRMTraceSwitch.Sw.TraceVerbose )
							Trace.WriteLine( string.Format(CultureInfo.InvariantCulture,"[V]CRMWrapper4 GetAllUserPrivileges UserName: {0}, privilege: {1}", userName, p.name),CRMTraceSwitch.Sw.Info);
					}
				}
				if ( dicPriv.Count != 0 )
					CurrentCache.InsertLong(ckey, dicPriv);
			}
			catch (SoapException sx)
			{
				if ( CRMTraceSwitch.Sw.TraceError )
					Trace.WriteLine( string.Format(CultureInfo.InvariantCulture,"[E]CRMWrapper4 GetAllUserPrivileges  ex: {0}-{1}", sx, sx.Detail.InnerText),CRMTraceSwitch.Sw.Info);
				throw;
			}
			catch (CRMWrapperException wx)
			{
				if ( CRMTraceSwitch.Sw.TraceError )
					Trace.WriteLine( string.Format(CultureInfo.InvariantCulture,"[E]CRMWrapper4 GetAllUserPrivileges ex: {0}}", wx),CRMTraceSwitch.Sw.Info);
				throw;
			}
			catch (Exception ex)
			{
				if ( CRMTraceSwitch.Sw.TraceError )
					Trace.WriteLine( string.Format(CultureInfo.InvariantCulture,"[E]CRMWrapper4 GetAllUserPrivileges ex: {0}", ex),CRMTraceSwitch.Sw.Info);
				throw;
			}
			if ( CRMTraceSwitch.Sw.TraceVerbose )
				Trace.WriteLine( string.Format(CultureInfo.InvariantCulture,"[V]CRMWrapper4 GetAllUserPrivileges END UserName: {0}, Count: {1}", userName, dicPriv.Count),CRMTraceSwitch.Sw.Info);
			return dicPriv;
		}


		
		#endregion Permissions and Privileges related functions
		
		#region BusinessUnits related functions

		/// <summary>
		/// Retrieve all Business Units using admin call, insert them in a sorted dictionnary
		/// </summary>
		public override SortedDictionary<Guid,ADNDynBusinessUnit> GetAllBusinessUnits()
		{
			string ckey         =   string.Format("GetAllBusinessUnits_{0}_{1}",OrganizationName,CrmVersion).Replace(' ','_').Replace(',','_');
			if (CurrentCache.Exists(ckey))
			{
				if ( CRMTraceSwitch.Sw.TraceVerbose )
					Trace.WriteLine( "[V]CRMWrapper4 GetAllBusinessUnits found in cache.",CRMTraceSwitch.Sw.Info);
				return (SortedDictionary<Guid, ADNDynBusinessUnit>)CurrentCache.Get(ckey);
			}
			BusinessEntity[] bu  =   null;
			SortedDictionary<Guid,ADNDynBusinessUnit> DicBu	=	new SortedDictionary<Guid,ADNDynBusinessUnit>();
			try
			{
				QueryExpression qe		    =   new QueryExpression();
				qe.EntityName			    =   EntityName.businessunit.ToString();
				qe.ColumnSet			    =   new AllColumns();
								
				ConditionExpression ce		=   new ConditionExpression();
				ce.AttributeName			=   CrmStr.isdisabled;
				ce.Operator					=   ConditionOperator.NotEqual;
				ce.Values                   =   new object[]{true};

				qe.Criteria					=   new FilterExpression();
				qe.Criteria.FilterOperator	=   LogicalOperator.And;
				qe.Criteria.Conditions		=   new ConditionExpression[] { ce };

				// Create the Request Object
				RetrieveMultipleRequest retrievePrincipal = new RetrieveMultipleRequest();

				// Set the Request Object's Properties
				retrievePrincipal.Query		=   qe;
				retrievePrincipal.ReturnDynamicEntities =   true;

				// Execute the Request
				RetrieveMultipleResponse principalResponse = (RetrieveMultipleResponse)adminService4.ExecuteRaw(retrievePrincipal);
				bu						    =	principalResponse.BusinessEntityCollection.BusinessEntities;
				int nb					    =	bu.GetUpperBound(0);
				if ( CRMTraceSwitch.Sw.TraceVerbose )
					Trace.WriteLine( string.Format(CultureInfo.InvariantCulture,"[V]CRMWrapper4 GetAllBusinessUnits upperBound(0): {0}", nb),CRMTraceSwitch.Sw.Info);
				for (int i = 0; i <= nb; i++)
				{
					DynamicEntity b		    =   (DynamicEntity)(bu[i]);
					InternalDynamicEntity n =   new InternalDynamicEntity(b);
					ADNDynBusinessUnit dbu  =   new ADNDynBusinessUnit(this,n,null,null);
					if ( CRMTraceSwitch.Sw.TraceVerbose )
						Trace.WriteLine( string.Format(CultureInfo.InvariantCulture,"[V]CRMWrapper4 GetAllBusinessUnits Adding: {0}, parent: {1}", 
							dbu.name,(dbu.parentbusinessunitid == Guid.Empty)? string.Empty:dbu.parentbusinessunitName),CRMTraceSwitch.Sw.Info);
					if ( dbu.parentbusinessunitid == Guid.Empty  )
						_InnerBusinessUnit  =   dbu;
					DicBu.Add(dbu.businessunitid, dbu);
				}
				if ( DicBu.Count > 0 )
					CurrentCache.InsertLong(ckey, DicBu);
			}
			catch (SoapException sx)
			{
				string msg  =   string.Format("[E]CRMWrapper4 GetAllBusinessUnits  ex: {0}-{1}", sx, sx.Detail.InnerText);
				if ( CRMTraceSwitch.Sw.TraceError )
					Trace.WriteLine( msg,CRMTraceSwitch.Sw.Info);
				throw;
			}
			catch (CRMWrapperException )
			{
				throw;
			}
			catch (Exception ex)
			{
				string msg  =   string.Format("[E]CRMWrapper4 GetAllBusinessUnits ex: {0}", ex);
				if ( CRMTraceSwitch.Sw.TraceError )
					Trace.WriteLine( msg,CRMTraceSwitch.Sw.Info);
				throw;
			}
			return DicBu;
		}

		/// <summary>
		/// Find a Bu using its Guid
		/// </summary>
		public override ADNDynBusinessUnit GetBusinessUnit(Guid businessunitid)
		{
			if ( CRMTraceSwitch.Sw.TraceVerbose )
				Trace.WriteLine( string.Format(CultureInfo.InvariantCulture,"[V]CRMWrapper4 GetBusinessUnit businessunitid: {0}",businessunitid),CRMTraceSwitch.Sw.Info);
			SortedDictionary<Guid,ADNDynBusinessUnit> dicBu	= GetAllBusinessUnits();
			if ( dicBu.ContainsKey(businessunitid) )
				return dicBu[businessunitid];
			if ( CRMTraceSwitch.Sw.TraceVerbose )
				Trace.WriteLine( string.Format(CultureInfo.InvariantCulture,"[V]CRMWrapper4 GetBusinessUnit NOT FOUND businessunitid: {0}",businessunitid),CRMTraceSwitch.Sw.Info);
			return null;
		}

		/// <summary>
		/// Find Name for a Bu given its Guid
		/// </summary>
		public override string GetBusinessUnitName(Guid businessunitid)
		{
			if ( CRMTraceSwitch.Sw.TraceVerbose )
				Trace.WriteLine( string.Format(CultureInfo.InvariantCulture,"[V]CRMWrapper4 GetBusinessUnitName businessunitid: {0}",businessunitid),CRMTraceSwitch.Sw.Info);
			SortedDictionary<Guid,ADNDynBusinessUnit> dicBu	= GetAllBusinessUnits();
			if ( dicBu.ContainsKey(businessunitid) )
				return dicBu[businessunitid].name;
			if ( CRMTraceSwitch.Sw.TraceVerbose )
				Trace.WriteLine( string.Format(CultureInfo.InvariantCulture,"[V]CRMWrapper4 GetBusinessUnitName NOT FOUND businessunitid: {0}",businessunitid),CRMTraceSwitch.Sw.Info);
			return string.Empty;
		}
		
		#endregion BusinessUnits related functions

		#region roles related functions

		/// <summary>
		/// Return all roles in an array
		/// </summary>
		public override InternalBusinessEntityArray GetAllRoles()
		{
			string ckey						= string.Format("GetAllRoles_{0}_{1}",OrganizationName,CrmVersion).Replace(' ','_').Replace(',','_');
			if (CurrentCache.Exists(ckey))
				return (InternalBusinessEntityArray)CurrentCache.Get(ckey);
			BusinessEntity[] bu				= null;
			InternalBusinessEntityArray cbu				= null;
			 

			try
			{
				QueryExpression qe			= new QueryExpression();
				qe.EntityName				= EntityName.role.ToString();
				qe.ColumnSet				= new AllColumns();

				ConditionExpression ce		= new ConditionExpression();
				ce.AttributeName			= CrmStr.roleid;
				ce.Operator					= ConditionOperator.NotNull;

				qe.Criteria					= new FilterExpression();
				qe.Criteria.FilterOperator	= LogicalOperator.And;
				qe.Criteria.Conditions		= new ConditionExpression[] { ce };


				RetrieveMultipleRequest retrievePrincipal = new RetrieveMultipleRequest();

				retrievePrincipal.Query		= qe;

				// Execute the Request
				RetrieveMultipleResponse principalResponse = (RetrieveMultipleResponse)adminService4.ExecuteRaw(retrievePrincipal);
				bu                          =   principalResponse.BusinessEntityCollection.BusinessEntities;
				cbu                         =   new InternalBusinessEntityArray(bu);
				if ( bu.GetUpperBound(0) >= 0 )
					CurrentCache.InsertLong(ckey, cbu);
			}
			catch (SoapException sx)
			{
				if ( CRMTraceSwitch.Sw.TraceError )
					Trace.WriteLine( string.Format(CultureInfo.InvariantCulture,"[E]CRMWrapper4 GetAllRoles  ex: {0}-{1}", sx, sx.Detail.InnerText),CRMTraceSwitch.Sw.Info);
				throw;
			}
			catch (CRMWrapperException )
			{
				throw;
			}
			catch (Exception ex)
			{
				if ( CRMTraceSwitch.Sw.TraceError )
					Trace.WriteLine( string.Format(CultureInfo.InvariantCulture,"[E]CRMWrapper4 GetAllRoles ex: {0}", ex),CRMTraceSwitch.Sw.Info);
				throw;
			}
			return cbu;
		}

		/// <summary>
		/// Renvoie la liste de tous les noms de roles 
		/// sous forme d'un tableau de strings
		/// </summary>
		public override string[] GetStrAllRoles()
		{
			string ckey = string.Format("GetStrAllRolesTab{0}_{1}",OrganizationName,CrmVersion).Replace(' ','_').Replace(',','_');
			if (CurrentCache.Exists(ckey))
			{
				if ( CRMTraceSwitch.Sw.TraceVerbose )
					Trace.WriteLine( "[V]CRMWrapper4 GetStrAllRoles[] found in cache.",CRMTraceSwitch.Sw.Info);
				return (string[])CurrentCache.Get(ckey);
			}
			BusinessEntity[] bu = null;
			try
			{
				InternalBusinessEntityArray b0  =   GetAllRoles();
				bu                              =   (BusinessEntity[])b0.Content;
			}
			catch (SoapException sx)
			{
				if ( CRMTraceSwitch.Sw.TraceError )
					Trace.WriteLine( string.Format(CultureInfo.InvariantCulture,"[E]CRMWrapper4 GetStrRoles sex: {0}-{1}", sx, sx.Detail.InnerText),CRMTraceSwitch.Sw.Info);
				throw new CRMWrapperException("GetStrAllRoles Sx", sx);
			}
			catch (CRMWrapperException)
			{
				throw;
			}
			catch (Exception ex)
			{
				if ( CRMTraceSwitch.Sw.TraceError )
					Trace.WriteLine( string.Format(CultureInfo.InvariantCulture,"[E]CRMWrapper4 GetStrRoles ex: {0}", ex),CRMTraceSwitch.Sw.Info);
				throw new CRMWrapperException("GetStrAllRoles ex", ex);
			}

			SortedDictionary<string, role> dicRole = new SortedDictionary<string, role>();
			foreach (BusinessEntity b in bu)
			{
				role r				=   (role)b;
				string strBu		=   GetBusinessUnitName(r.businessunitid.Value);
				if ( strBu == string.Empty )
					continue;
				string roleName		=   string.Format("{0}.{1}",strBu,r.name);
				if (!dicRole.ContainsKey(roleName))
				{
					dicRole.Add(roleName, r);
					if ( CRMTraceSwitch.Sw.TraceVerbose )
						Trace.WriteLine( string.Format(CultureInfo.InvariantCulture,"[V]CRMWrapper4 UserName : {0}, role : {1}", userName, roleName),CRMTraceSwitch.Sw.Info);
				}
			}
			string[] roles			=   new string[dicRole.Count];
			int i					=   0;
			StringBuilder sb		=   new StringBuilder();
			foreach (KeyValuePair<string, role> kvp in dicRole)
			{
				roles[i++]			=   kvp.Key;
				if ( CRMTraceSwitch.Sw.TraceVerbose )
					sb.AppendFormat("{0}-", kvp.Key);
			}
			if ( CRMTraceSwitch.Sw.TraceVerbose )
				Trace.WriteLine( string.Format(CultureInfo.InvariantCulture,"[V]CRMWrapper4 GetStrAllRoles:  {0}, nbroles: {1}", sb.ToString(), i),CRMTraceSwitch.Sw.Info);
			if ( i > 0 )
				CurrentCache.InsertLong(ckey,roles);
			return roles;
		}

		/// <summary>
		/// Return users crm rols as an array
		/// </summary>
		public override InternalBusinessEntityArray GetUserRoles(Guid UserID2Test)
		{
			string ckey						=   string.Format("GetUserRoles_{0}_{1}",UserID2Test,CrmVersion).Replace(' ','_').Replace(',','_');
			if (CurrentCache.Exists(ckey))
			{
				if ( CRMTraceSwitch.Sw.TraceVerbose )
					Trace.WriteLine( string.Format(CultureInfo.InvariantCulture,"[V]CRMWrapper4 GetUserRoles found in cache ckey: {0}", ckey),CRMTraceSwitch.Sw.Info);
				return (InternalBusinessEntityArray)CurrentCache.Get(ckey);
			}
			BusinessEntity[] bu				=   null;
			InternalBusinessEntityArray cbu	=   null;
			
			try
			{
				QueryExpression qe			=   new QueryExpression();
				qe.EntityName				=   EntityName.role.ToString();
				qe.ColumnSet				=   new AllColumns();

				LinkEntity le				=   new LinkEntity();
				le.LinkFromEntityName		=   qe.EntityName;
				le.LinkFromAttributeName	=   CrmStr.roleid;
				le.LinkToEntityName			=   CrmStr.systemuserroles;
				le.LinkToAttributeName		=   CrmStr.roleid;

				LinkEntity le2				=   new LinkEntity();
				le2.LinkFromEntityName		=   CrmStr.systemuserroles;
				le2.LinkFromAttributeName	=   CrmStr.systemuserid;
				le2.LinkToEntityName		=   EntityName.systemuser.ToString();
				le2.LinkToAttributeName		=   CrmStr.systemuserid;

				ConditionExpression ce		=   new ConditionExpression();
				ce.AttributeName			=   CrmStr.systemuserid;
				ce.Operator					=   ConditionOperator.Equal;
				ce.Values					=   new object[] { UserID2Test };

				le2.LinkCriteria			=   new FilterExpression();
				le2.LinkCriteria.Conditions =   new ConditionExpression[] { ce };

				le.LinkEntities				=   new LinkEntity[] { le2 };
				qe.LinkEntities				=   new LinkEntity[] { le };


				RetrieveMultipleRequest retrievePrincipal = new RetrieveMultipleRequest();

				retrievePrincipal.Query		=   qe;

				RetrieveMultipleResponse principalResponse = (RetrieveMultipleResponse)adminAdminExecuteRaw(retrievePrincipal);
				bu							=   principalResponse.BusinessEntityCollection.BusinessEntities;
				cbu                         =   new InternalBusinessEntityArray(bu);
				int nb						=   bu.GetUpperBound(0)+1;
				if ( nb > 0 )
					CurrentCache.InsertLong(ckey, cbu);
				if ( CRMTraceSwitch.Sw.TraceVerbose )
					Trace.WriteLine( string.Format(CultureInfo.InvariantCulture,"[V]CRMWrapper4 GetUserRoles  END userId: {0}, nbRoles: {1}", UserID2Test, nb),CRMTraceSwitch.Sw.Info);
			}
			catch (SoapException sx)
			{
				string msg  =   string.Format("[E]CRMWrapper4 GetUserRoles  ex: {0}-{1}", sx, sx.Detail.InnerText);
				if ( CRMTraceSwitch.Sw.TraceError )
					Trace.WriteLine( msg,CRMTraceSwitch.Sw.Info);
				throw new CRMWrapperException(msg, sx);
			}
			catch (CRMWrapperException)
			{
				throw;
			}
			catch (Exception ex)
			{
				string msg  =   string.Format("[E]CRMWrapper4 GetUserRoles ex: {0}", ex);
				if ( CRMTraceSwitch.Sw.TraceError )
					Trace.WriteLine( msg,CRMTraceSwitch.Sw.Info);
				throw new CRMWrapperException(msg, ex);
			}
			return cbu;
		}

		// <summary>
		/// Build an array of strings with names of all roles attached to this user, each element is formated with as 'businessunit.rolename'
		/// </summary>
		public override string[] GetStrUserRoles(Guid userId2Test)
		{
			string ckey				=   string.Format("GetStrUserRoles_{0}_{1}", userId2Test,CrmVersion).Replace(' ','_').Replace(',','_');
			if (CurrentCache.Exists(ckey))
			{
				if ( CRMTraceSwitch.Sw.TraceVerbose )
					Trace.WriteLine( string.Format(CultureInfo.InvariantCulture,"[V]CRMWrapper4 GetStrUserRoles found in cache ckey: {0}", ckey),CRMTraceSwitch.Sw.Info);
				return (string[])CurrentCache.Get(ckey);
			}
			BusinessEntity[] bu     =   null;

			try
			{
				bu					=   (BusinessEntity[])GetUserRoles(userId2Test).Content;
			}
			catch (SoapException sx)
			{
				string msg  =   string.Format("[E]CRMWrapper4 GetStrUserRoles  ex: {0}-{1}", sx, sx.Detail.InnerText);
				if ( CRMTraceSwitch.Sw.TraceError )
					Trace.WriteLine( msg,CRMTraceSwitch.Sw.Info);
				throw new CRMWrapperException(msg, sx);
			}
			catch (CRMWrapperException)
			{
				throw;
			}
			catch (Exception ex)
			{
				string msg  =   string.Format("[E]CRMWrapper4 GetStrUserRoles ex: {0}", ex);
				if ( CRMTraceSwitch.Sw.TraceError )
					Trace.WriteLine( msg,CRMTraceSwitch.Sw.Info);
				throw new CRMWrapperException(msg, ex);
			}
			string[] roles			= new string[0];
			string strr				= string.Empty;
			if (bu.GetUpperBound(0) >= 0)
			{
				StringBuilder sb    = new StringBuilder();
				foreach (BusinessEntity b in bu)
				{
					role r          = (role)b;
					string strBu	= GetBusinessUnitName(r.businessunitid.Value);
					if ( strBu == string.Empty )
						continue;
					sb.AppendFormat("{0}.{1};", strBu,r.name);
				}
				strr				= sb.ToString();
				roles               = strr.Split(";".ToCharArray(),StringSplitOptions.RemoveEmptyEntries);
				CurrentCache.InsertLong(ckey, roles);
			}
			if ( CRMTraceSwitch.Sw.TraceVerbose )
				Trace.WriteLine( string.Format(CultureInfo.InvariantCulture,"[V]CRMWrapper4 GetStrUserRoles END UserId: {0}, roles: '{1}'", userId2Test, strr),CRMTraceSwitch.Sw.Info);
			return roles;
		}

		/// <summary>
		/// Try to check if the role sent is amongst the roles of this user
		/// </summary>
		public override bool IsInCRMUserRoles(string role2Test,Guid userId2Test)
		{
			if ( CRMTraceSwitch.Sw.TraceVerbose )
				Trace.WriteLine( string.Format(CultureInfo.InvariantCulture,"[V]CRMWrapper4 IsInCRMUserRoles BEG role2Test: {0}.",role2Test),CRMTraceSwitch.Sw.Info);
			bool ret			=	false;
			BusinessEntity[] bu = null;

			try
			{
				bu				=   (BusinessEntity[])GetUserRoles(userId2Test).Content;
			}
			catch (SoapException sx)
			{
				string msg      =   string.Format("[E]CRMWrapper4 IsInCRMUserRoles ex: {0}-{1}", sx, sx.Detail.InnerText);
				if ( CRMTraceSwitch.Sw.TraceError )
					Trace.WriteLine( msg,CRMTraceSwitch.Sw.Info);
				throw new CRMWrapperException(msg, sx);
			}
			catch (CRMWrapperException)
			{
				throw;
			}
			catch (Exception ex)
			{
				string msg      =   string.Format("[E]CRMWrapper4 IsInCRMUserRoles ex: {0}", ex);
				if ( CRMTraceSwitch.Sw.TraceError )
					Trace.WriteLine( msg,CRMTraceSwitch.Sw.Info);
				throw new CRMWrapperException(msg, ex);
			}
			int idx		        =	role2Test.IndexOf('.');
			if ( idx != -1 )
				role2Test		=	role2Test.Substring(idx+1);
			if ( CRMTraceSwitch.Sw.TraceVerbose )
				Trace.WriteLine( string.Format(CultureInfo.InvariantCulture,"[V]CRMWrapper4 IsInCRMUserRoles reduced role2Test: '{0}'.",role2Test),CRMTraceSwitch.Sw.Info);
			if (bu.GetUpperBound(0) >= 0)
			{
				foreach (BusinessEntity b in bu)
				{
					role r      =   (role)b;
					if ( r.businessunitid.Value == businessUnitId && r.name == role2Test )
					{
						if ( CRMTraceSwitch.Sw.TraceVerbose )
							Trace.WriteLine( string.Format(CultureInfo.InvariantCulture,"[V]CRMWrapper4 IsInCRMUserRoles role2Test: '{0}' found.",role2Test),CRMTraceSwitch.Sw.Info);
						ret	    =	true;
						break;
					}
				}
			}
			if ( CRMTraceSwitch.Sw.TraceInfo )
				Trace.WriteLine( string.Format(CultureInfo.InvariantCulture,"[V]CRMWrapper4 IsInCRMUserRoles END roles: '{0}', ret: {1}", role2Test, ret),CRMTraceSwitch.Sw.Info);
			return ret;
		}

		#endregion roles related functions

		#region metadata related methods

		public override string GetTimestamp()
		{
			RetrieveTimestampRequest req    =   new RetrieveTimestampRequest(); 
			RetrieveTimestampResponse resp  =   (RetrieveTimestampResponse)adminMetaService4.ExecuteRaw(req); 
			LastTimestamp                   =   resp.Timestamp;
			return resp.Timestamp;
		}
		
		CrmMetadata[] internalRetrieveMetadataRaw(MetadataItems f,bool isAdmin)
		{
			
			if ( CRMTraceSwitch.Sw.TraceVerbose )
				Trace.WriteLine( string.Format(CultureInfo.InvariantCulture,"[V]CRMWrapper4 internalRetrieveMetadataRaw BEG EntityFlags: {0}, isAdsmin: {1}", f,isAdmin),CRMTraceSwitch.Sw.Info);
			CrmMetadata[] meta  =   null;
			try
			{
				if (isAdmin)
						meta   =   adminMetaService4.RetrieveMetadataRaw(f);
				else    meta   =   userMetaService4.RetrieveMetadataRaw(f);
				if ( CRMTraceSwitch.Sw.TraceVerbose )
					Trace.WriteLine( string.Format(CultureInfo.InvariantCulture,"[V]CRMWrapper4 internalRetrieveMetadataRaw END count: {0}",meta.Length),CRMTraceSwitch.Sw.Info);
				return meta;
			}
			catch (SoapException sx)
			{
				string msg  =   string.Format("[E]CRMWrapper4 internalRetrieveMetadataRaw  ex: {0}-{1}", sx, sx.Detail.InnerText);
				if ( CRMTraceSwitch.Sw.TraceError )
					Trace.WriteLine( msg,CRMTraceSwitch.Sw.Info);
				throw new CRMWrapperException(msg, sx);
			}
			catch (CRMWrapperException)
			{
				throw;
			}
			catch (Exception ex)
			{
				string msg  =   string.Format("[E]CRMWrapper4 internalRetrieveMetadataRaw ex: {0}", ex);
				if ( CRMTraceSwitch.Sw.TraceError )
					Trace.WriteLine( msg,CRMTraceSwitch.Sw.Info);
				throw new CRMWrapperException(msg, ex);
			}
		}

		public override InternalMetadata internalRetrieveMetadata(EntityInternalItems f,bool isAdmin)
		{
			
			if ( CRMTraceSwitch.Sw.TraceVerbose )
				Trace.WriteLine( string.Format(CultureInfo.InvariantCulture,"[V]CRMWrapper4 internalRetrieveMetadata  EntityFlags: {0}, isAdsmin: {1}", f,isAdmin),CRMTraceSwitch.Sw.Info);
			try
			{
				if (isAdmin)
					return adminMetaService.RetrieveMetadata(f);
				return userMetaService.RetrieveMetadata(f);
			}
			catch (SoapException sx)
			{
				string msg  =   string.Format("[E]CRMWrapper4 internalRetrieveMetadata ex: {0}-{1}", sx, sx.Detail.InnerText);
				if ( CRMTraceSwitch.Sw.TraceError )
					Trace.WriteLine( msg,CRMTraceSwitch.Sw.Info);
				throw new CRMWrapperException(msg, sx);
			}
			catch (CRMWrapperException)
			{
				throw;
			}
			catch (Exception ex)
			{
				string msg  =   string.Format("[E]CRMWrapper4 internalRetrieveMetadata ex: {0}", ex);
				if ( CRMTraceSwitch.Sw.TraceError )
					Trace.WriteLine( msg,CRMTraceSwitch.Sw.Info);
				throw new CRMWrapperException(msg, ex);
			}
		}

		/// <summary>
		/// Retrieve the object type code for the specified entity
		/// </summary>
		/// <param name="entityName">Schema name of the entity</param>
		/// <returns>Object type code of entity</returns>
		public override int GetObjectTypeCode(string entityName)
		{
			if ( CRMTraceSwitch.Sw.TraceVerbose )
				Trace.WriteLine( string.Format(CultureInfo.InvariantCulture,"[V]CRMWrapper4 GetObjectTypeCode  entityName: {0}", entityName),CRMTraceSwitch.Sw.Info);
			try
			{
			EntityMetadata entity   =   internalRetrieveEntityMetadataRaw(entityName, EntityItems.EntityOnly,true);
			int ObjectTypeCode      =   entity.ObjectTypeCode.Value;
			if ( CRMTraceSwitch.Sw.TraceVerbose )
				Trace.WriteLine( string.Format(CultureInfo.InvariantCulture,"[V]CRMWrapper4 GetObjectTypeCode  entityName: {0}, ObjectTypeCode: {1}", entityName, ObjectTypeCode),CRMTraceSwitch.Sw.Info);
			return ObjectTypeCode;              
			}
			catch (SoapException sx)
			{
				if ( CRMTraceSwitch.Sw.TraceError )
					Trace.WriteLine( string.Format(CultureInfo.InvariantCulture,"[E]CRMWrapper4 GetObjectTypeCode  ex: {0}-{1}", sx, sx.Detail.InnerText),CRMTraceSwitch.Sw.Info);
				throw new CRMWrapperException("GetObjectTypeCode Sx", sx);
			}
			catch (CRMWrapperException)
			{
				throw;
			}
			catch (Exception ex)
			{
				if ( CRMTraceSwitch.Sw.TraceError )
					Trace.WriteLine( string.Format(CultureInfo.InvariantCulture,"[E]CRMWrapper4 GetObjectTypeCode ex: {0}", ex),CRMTraceSwitch.Sw.Info);
				throw new CRMWrapperException("GetObjectTypeCode ex", ex);
			}
		}

		/// <summary>
		/// Retrieve the display name for the specified entity
		/// </summary>
		/// <param name="entityName">Schema name of the entity</param>
		/// <returns>Display name of the entity</returns>
		public override string GetDisplayName(string entityName)
		{
			if ( CRMTraceSwitch.Sw.TraceVerbose )
				Trace.WriteLine( string.Format(CultureInfo.InvariantCulture,"[V]CRMWrapper4 GetDisplayName  entityName: {0}", entityName),CRMTraceSwitch.Sw.Info);
			try
			{
				EntityMetadata entity       =   internalRetrieveEntityMetadataRaw(entityName, EntityItems.EntityOnly,true);
				string displayName          =   entity.DisplayName.UserLocLabel.Label;/// To Check              
				if ( CRMTraceSwitch.Sw.TraceVerbose )
					Trace.WriteLine( string.Format(CultureInfo.InvariantCulture,"[V]CRMWrapper4 GetDisplayName  entityName: {0}, DisplayName: {1}", entityName, displayName),CRMTraceSwitch.Sw.Info);
				return displayName;              
			}
			catch (SoapException sx)
			{
				if ( CRMTraceSwitch.Sw.TraceError )
					Trace.WriteLine( string.Format(CultureInfo.InvariantCulture,"[E]CRMWrapper4 GetDisplayName  ex: {0}-{1}", sx, sx.Detail.InnerText),CRMTraceSwitch.Sw.Info);
				throw new CRMWrapperException("GetDisplayName Sx", sx);
			}
			catch (CRMWrapperException)
			{
				throw;
			}
			catch (Exception ex)
			{
				if ( CRMTraceSwitch.Sw.TraceError )
					Trace.WriteLine( string.Format(CultureInfo.InvariantCulture,"[E]CRMWrapper4 GetDisplayName ex: {0}", ex),CRMTraceSwitch.Sw.Info);
				throw new CRMWrapperException("GetDisplayName ex", ex);
			}
		}

		/// <summary>
		/// Send the custom entities name to a delegate to fill a list
		/// </summary>
		public override int IterateMetaEntities(EntityInternalItems f, bool isAdmin,bool customOnly,EntityNameDelegate fn)
		{
			if ( CRMTraceSwitch.Sw.TraceVerbose )
				Trace.WriteLine( string.Format(CultureInfo.InvariantCulture,"[V]CRMWrapper4 IterateMetaEntities BEG customOnly: {0}, isAdmin: {1}", customOnly, isAdmin),CRMTraceSwitch.Sw.Info);
			MetadataItems fl            =   Crm4MetadataWebService.ConvertMetaDataFlag(f);
			CrmMetadata[] metadata      =   internalRetrieveMetadataRaw(fl, isAdmin);
			// Iterate through all entities and only add custom entities
			int cnt                     =   0;
			foreach (EntityMetadata m in metadata)
			{
				if ((!customOnly || m.IsCustomEntity.Value) && !string.IsNullOrEmpty(m.LogicalName))
				{
					if (CRMTraceSwitch.Sw.TraceVerbose)
						Trace.WriteLine( string.Format(CultureInfo.InvariantCulture,"[V]CRMWrapper4 IterateMetaEntities LogicalName: '{0}'", m.LogicalName), CRMTraceSwitch.Sw.Info);
					if ((m.DisplayName != null) && (m.DisplayName.UserLocLabel != null))
						fn(m.LogicalName, m.DisplayName.UserLocLabel.Label);
					else
						fn(m.LogicalName, m.LogicalName);
					cnt++;
				}
				else
				{
					if (CRMTraceSwitch.Sw.TraceVerbose)
						Trace.WriteLine( string.Format(CultureInfo.InvariantCulture,"[V]CRMWrapper4 IterateMetaEntities not retained entity : '{0}'", m.SchemaName.ToString()), CRMTraceSwitch.Sw.Info);
				}
			}
			if ( CRMTraceSwitch.Sw.TraceVerbose )
				Trace.WriteLine( string.Format(CultureInfo.InvariantCulture,"[V]CRMWrapper4 IterateMetaEntities END Count: {0}.", cnt),CRMTraceSwitch.Sw.Info);
			return cnt;
		}


		#endregion metadata related methods
		
		#region special for DynEntity

		/// <summary>
		/// conversion between Crm Attributes types and .net types
		/// </summary>
		public Type ConvertAttributeType2Type(AttributeType EntAtt)
		{
			Type tmp;

			switch (EntAtt)
			{
				case AttributeType.DateTime:
					tmp = typeof(System.DateTime);
					break;

				case AttributeType.Boolean:
					tmp = typeof(System.Boolean);
					break;

				case AttributeType.Money:
				case AttributeType.Decimal:
					tmp = typeof(System.Decimal);
					break;

				case AttributeType.Status:
				case AttributeType.Picklist:
				case AttributeType.Integer:
					tmp = typeof(System.Int32);
					break;

				case AttributeType.PrimaryKey:
				case AttributeType.Owner:
				case AttributeType.Customer:
				case AttributeType.Lookup:
				case AttributeType.UniqueIdentifier:
					tmp = typeof(System.Guid);
					break;

				case AttributeType.Float: // beware diffreent from v3
					tmp = typeof(System.Double);
					break;

				default:
					// This sample returns strings for all data types by default
					tmp = typeof(string);
					break;
				}
			if ( CRMDynTraceSwitch.Sw.TraceVerbose )
				Trace.WriteLine( string.Format(CultureInfo.InvariantCulture,"[V]CRMWrapper4 ConvertAttributeType2Type AttributeType: {0}, Type: {1}", EntAtt,tmp),CRMDynTraceSwitch.Sw.Info);
			return tmp;
		}
		
		
		public override PropertyDescriptorCollection StaticCreatePropertyDescriptorCollection(EntityInternalMetadata attribs)
		{
			AttributeMetadata[] attributes          =   ((EntityMetadata)attribs.Content).Attributes;
			DynEntity.LocalPropertyDescriptor[] pds =   new DynEntity.LocalPropertyDescriptor[attributes.Length];

			// Populate the Property Descriptor collection with Property descriptors
			for (int i = 0; i < attributes.Length; i++)
			{
				AttributeMetadata d                 =   attributes[i];
				if ( CRMDynTraceSwitch.Sw.TraceVerbose )
					Trace.WriteLine( string.Format(CultureInfo.InvariantCulture,"[V]CRMWrapper4 StaticCreatePropertyDescriptorCollection Attribute  i={0}, Name: {1}, Type: {2}",
						i, d.LogicalName,d.AttributeType.Value),CRMDynTraceSwitch.Sw.Info);
				if ( ( (d.DisplayMask.Value & DisplayMasks.ObjectTypeCode) == DisplayMasks.ObjectTypeCode ) && ( d.AttributeType.Value == AttributeType.Picklist ) ) 
					 pds[i]                         =   new DynEntity.LocalPropertyDescriptor(d.LogicalName, typeof(string));
				else pds[i]                         =   new DynEntity.LocalPropertyDescriptor(d.LogicalName, ConvertAttributeType2Type(d.AttributeType.Value));
			}
			return new PropertyDescriptorCollection(pds);
		}


		public override PropertyDescriptorCollection CreatePropertyDescriptorCollection(EntityInternalMetadata attribs,DicProperties dicProperty,bool filterWithProperties)
		{
			DynEntity.LocalPropertyDescriptor[] pds =   null;
			AttributeMetadata[] attributes          =   ((EntityMetadata)attribs.Content).Attributes;

			if ( CRMDynTraceSwitch.Sw.TraceVerbose )
				Trace.WriteLine( string.Format(CultureInfo.InvariantCulture,"[V]CRMWrapper4 CreatePropertyDescriptorCollection BEG filterWithProperties: {0}, dicProperty.Count: {1}",
					filterWithProperties,dicProperty.Count),CRMDynTraceSwitch.Sw.Info);
			if ( filterWithProperties && dicProperty.Count > 0 )
					pds                             =   new DynEntity.LocalPropertyDescriptor[dicProperty.Count];
			else    pds                             =   new DynEntity.LocalPropertyDescriptor[attributes.Length];

			// Populate the Property Descriptor collection with Property descriptors
			int count                               =   0;
			for (int i = 0; i < attributes.Length; i++)
			{
				AttributeMetadata d                 =   attributes[i];
				if (filterWithProperties && !dicProperty.ContainsKey(d.LogicalName)) /// ??????? To check
					continue;
				if ( CRMDynTraceSwitch.Sw.TraceVerbose )
					Trace.WriteLine( string.Format(CultureInfo.InvariantCulture,"[V]CRMWrapper4 CreatePropertyDescriptorCollection Attribute  i={0}, Name: {1}, TypeIsNull: {2}, Type: {3}",
						new object[]{count, d.LogicalName,d.AttributeType.IsNull,d.AttributeType.Value}),CRMDynTraceSwitch.Sw.Info);
				// Bug ??? When EntityReference attribute is picklist , should be string
				if ( ( (d.DisplayMask.Value & DisplayMasks.ObjectTypeCode) == DisplayMasks.ObjectTypeCode ) && ( d.AttributeType.Value == AttributeType.Picklist ) ) 
					 pds[count++]                   =   new DynEntity.LocalPropertyDescriptor(d.LogicalName, typeof(string));
				else pds[count++]                   =   new DynEntity.LocalPropertyDescriptor(d.LogicalName, ConvertAttributeType2Type(d.AttributeType.Value));
			}
			return new PropertyDescriptorCollection(pds);
		}
		
		/// <summary>
		/// Get the "value" of a property
		/// Based on the type of property, this method determines how to get the properties "value"
		/// With the exception of dates, this implementation  returns a user viewable string as the 
		/// value.  
		/// </summary>
		public override object GetPropertyValue(InternalProperty prop)
		{
			if ( CRMDynTraceSwitch.Sw.TraceVerbose )
				Trace.WriteLine( string.Format(CultureInfo.InvariantCulture,"[V]CRMWrapper4 GetPropertyValue: {0}", prop.Content),CRMDynTraceSwitch.Sw.Info);
			return GetPropertyValueRaw((Property)prop.Content);
		}

		public object GetPropertyValueRaw(Property prop)
		{
			// Based on the property type, we will determine what data should be returned to the 
			// Grid for display.  This sample includes some hard-coded default behavior that may
			// or may not be approriate for your needs.

			Type propertyType                   =   prop.GetType();

			if ( CRMDynTraceSwitch.Sw.TraceVerbose )
				Trace.WriteLine( string.Format(CultureInfo.InvariantCulture,"[V]CRMWrapper4 GetPropertyValueRaw BEG propertyType: {0}", propertyType.Name),CRMDynTraceSwitch.Sw.Info);

			if (propertyType == typeof(StringProperty))
			{
				return ((StringProperty)prop).Value;
			}
			if (propertyType == typeof(CrmDateTimeProperty))
			{
				// Convert the CRM date into a System.DateTime
				CrmDateTimeProperty dprop       =   (CrmDateTimeProperty)prop;
				CRM4Server.CrmDateTime cdate    =   dprop.Value;
				if ( !cdate.IsNull )
				{
					string dateTimeAsText = cdate.Value;
					return DateTime.Parse(dateTimeAsText, CultureInfo.InvariantCulture, DateTimeStyles.AdjustToUniversal);
				}
				return null; // ??? potential pb
			}
			if (propertyType == typeof(KeyProperty))
			{
				return ((KeyProperty)prop).Value.Value;
			}
			if (propertyType == typeof(LookupProperty))
			{
				return (((LookupProperty)prop).Value).Value;
			}
			if (propertyType == typeof(StateProperty))
			{
				return ((StateProperty)prop).Value;
			}
			if (propertyType == typeof(PicklistProperty))
			{
				return ((PicklistProperty)prop).Value.name;
			}
			if (propertyType == typeof(CrmMoneyProperty))
			{
				return ((CrmMoneyProperty)prop).Value.Value;
			}
			if (propertyType == typeof(CrmBooleanProperty))
			{
				return ((CrmBooleanProperty)prop).Value.Value;
			}

			if (propertyType == typeof(CrmDecimalProperty))
			{
				return ((CrmDecimalProperty)prop).Value.Value;
			}

			if (propertyType == typeof(CrmFloatProperty))
			{
				return ((CrmFloatProperty)prop).Value.Value;
			}

			if (propertyType == typeof(CrmNumberProperty))
			{
				return ((CrmNumberProperty)prop).Value.Value;
			}
			if (propertyType == typeof(CustomerProperty))
			{

				return ((CustomerProperty)prop).Value.Value;
			}
			if (propertyType == typeof(EntityNameReferenceProperty))
			{
				return ((EntityNameReferenceProperty)prop).Value.Value;
			}
			if (propertyType == typeof(OwnerProperty))
			{
				return ((OwnerProperty)prop).Value.Value;
			}
			if (propertyType == typeof(StatusProperty))
			{
				return ((StatusProperty)prop).Value.Value;
			}

			if (propertyType == typeof(UniqueIdentifierProperty))
			{
				return ((UniqueIdentifierProperty)prop).Value.Value;
			}
			// we return the Array length
			if (propertyType == typeof(DynamicEntityArrayProperty))
			{
				return ((DynamicEntityArrayProperty)prop).Value.Length;
			}
			// The property type is not supported
			string strerr   =   string.Format("[E]CRMWrapper4 GetPropertyValue unsupported property: {0} type:{1}",prop.Name,propertyType.GetType().Name);
			if ( CRMDynTraceSwitch.Sw.TraceError )
				Trace.WriteLine(strerr,CRMDynTraceSwitch.Sw.Info);

			throw new CRMWrapperException(strerr);
		}
		
		public override void FillDicProperties(InternalDynamicEntity crmdEntity, InternalColumnSet CSel, DicProperties dicProperty)
		{
			DynamicEntity dEntity    =   (DynamicEntity)crmdEntity.Content;
			if (CRMDynTraceSwitch.Sw.TraceVerbose)
				Trace.WriteLine( string.Format(CultureInfo.InvariantCulture,"[V]CRMWrapper4 FillDicProperties BEG entity: {0}.",dEntity.Name), CRMDynTraceSwitch.Sw.Info);
			ColumnSet ColSel         =   (CSel == null) ? null:(ColumnSet)CSel;
			foreach (Property ep in dEntity.Properties)
			{
				// We only take selected columns
				if (ColSel != null)
				{
					bool found      =   false;
					for (int i = 0; i < ColSel.Attributes.Length; i++)
					{
						if (ColSel.Attributes[i] == ep.Name)
						{
							found   =   true;
							break;
						}
					}
					if (!found)
						continue;
				}

				dicProperty.Add(ep.Name, new InternalProperty(ep));
				if (CRMDynTraceSwitch.Sw.TraceVerbose)
					Trace.WriteLine( string.Format(CultureInfo.InvariantCulture,"[V]CRMWrapper4 FillDicProperties entity: {0}, Adding Property name: {1}, type: {2}",
						dEntity.Name, ep.Name, ep), CRMDynTraceSwitch.Sw.Info);
			}
			if (CRMDynTraceSwitch.Sw.TraceVerbose)
				Trace.WriteLine( string.Format(CultureInfo.InvariantCulture,"[V]CRMWrapper4 FillDicProperties END entity: {0}, count: {1}.", 
					dEntity.Name,dicProperty.Count), CRMDynTraceSwitch.Sw.Info);
		}

		public override InternalDynamicEntity ToDynamicEntity(DynEntity dn)
		{
			if ( CRMDynTraceSwitch.Sw.TraceVerbose )
				Trace.WriteLine( string.Format(CultureInfo.InvariantCulture,"[V]CRMWrapper4 ToDynamicEntity BEG SchemaName: {0}", dn.SchemaName),CRMDynTraceSwitch.Sw.Info);
			return new InternalDynamicEntity(ToDynamicEntityRaw(dn));
		}

		public DynamicEntity ToDynamicEntityRaw(DynEntity dn)
		{
			if ( CRMDynTraceSwitch.Sw.TraceVerbose )
				Trace.WriteLine( string.Format(CultureInfo.InvariantCulture,"[V]CRMWrapper4 ToDynamicEntityRaw BEG SchemaName: {0}", dn.SchemaName),CRMDynTraceSwitch.Sw.Info);
			// Create the DynamicEntity object.
			DynamicEntity dEntity   =   new DynamicEntity();
			// Set the name of the entity type.
			dEntity.Name            =   dn.SchemaName;
			// Set the properties
			if ( CRMDynTraceSwitch.Sw.TraceVerbose )
				Trace.WriteLine( string.Format(CultureInfo.InvariantCulture,"[V]CRMWrapper4 ToDynamicEntityRaw properties count: {0}.", dn.Count),CRMDynTraceSwitch.Sw.Info);

			dEntity.Properties      =   new Property[dn.Count];
			int                 i   =   0;
			foreach (string s in dn.Keys)
			{
				if (s != null && dn.dicProperty.ContainsKey(s))
				{
					if ( CRMDynTraceSwitch.Sw.TraceVerbose )
						Trace.WriteLine( string.Format(CultureInfo.InvariantCulture,"[V]CRMWrapper4 ToDynamicEntityRaw [{0}] elements = [{1}]->[{2}]",
							i, s, GetPropertyValue(dn.dicProperty[s])),CRMDynTraceSwitch.Sw.Info);
					dEntity.Properties[i++] = (Property)dn.dicProperty[s].Content;
				}
			}
			return dEntity;
		}

		public override Guid CreateFromDynEntity(DynEntity dynEnt,bool isAdmin)
		{
			if ( CRMDynTraceSwitch.Sw.TraceVerbose )
				Trace.WriteLine( string.Format(CultureInfo.InvariantCulture,"[V]CRMWrapper4 CreateFromDynEntity BEG SchemaName: {0}, isAdmin: {1}", dynEnt.SchemaName,isAdmin),CRMDynTraceSwitch.Sw.Info);
			// Create the DynamicEntity object.
			DynamicEntity dEntity               =   new DynamicEntity();
			EntityConfig Tconfig                =   new EntityConfig(this,dynEnt.SchemaName);

			// Set the name of the entity type.
			dEntity.Name                        =   dynEnt.SchemaName;
			// Set the properties 
			if ( CRMDynTraceSwitch.Sw.TraceVerbose )
				Trace.WriteLine( string.Format(CultureInfo.InvariantCulture,"[V]CRMWrapper4 CreateFromDynEntity dicProperty.Count: {0}",dynEnt.dicProperty.Count),CRMDynTraceSwitch.Sw.Info);
			List<Property> Lst                  =   new List<Property>();
			foreach (KeyValuePair<string, InternalProperty> kvp in dynEnt.dicProperty)
			{
				Property p                      =   (Property)kvp.Value.Content;
				if (!Tconfig.attributesDic.ContainsKey(p.Name))
				{
					if ( CRMDynTraceSwitch.Sw.TraceVerbose )
						Trace.WriteLine( string.Format(CultureInfo.InvariantCulture,"[V]CRMWrapper4 CreateFromDynEntity Property not in V4 Name: {0}", p.Name),CRMDynTraceSwitch.Sw.Info);
					//???? bug
					if ( p.Name != CrmStr.calendarrules )
						continue;
				}
				if (  ( p.Name != CrmStr.calendarrules ) && !Util4.ExtractAttributeFieldAsBool(Tconfig[p.Name], InternalAttributeFields.ValidForCreate))
				{
					if ( CRMDynTraceSwitch.Sw.TraceVerbose )
						Trace.WriteLine( string.Format(CultureInfo.InvariantCulture,"[V]CRMWrapper4 CreateFromDynEntity Property Not valid for create Name: {0}", p.Name),CRMDynTraceSwitch.Sw.Info);
					continue;
				}
				Lst.Add(p);
				if ( CRMDynTraceSwitch.Sw.TraceVerbose )
					Trace.WriteLine( string.Format(CultureInfo.InvariantCulture,"[V]CRMWrapper4 CreateFromDynEntity adding key: {0}, value: {1}", kvp.Key,GetPropertyValueRaw(p)),CRMDynTraceSwitch.Sw.Info);
			}
			dEntity.Properties                  =   new Property[Lst.Count];
			int i                               =   0;
			foreach(Property p in Lst)
				dEntity.Properties[i++]         =   p;

			// Create the target.
			TargetCreateDynamic targetCreate    =   new TargetCreateDynamic();
			targetCreate.Entity                 =   dEntity;
			// Create the request object.
			CreateRequest create                =   new CreateRequest();

			// Set the properties of the request object.
			create.Target                       =   targetCreate;
			CreateResponse created              =   null;
			try
			{
				// Execute the request
				if (isAdmin)
					created                     =   (CreateResponse)adminExecuteRaw(create);
				else
					created                     =   (CreateResponse)userExecuteRaw(create);
			}
			catch(Exception ex)
			{
				if ( CRMDynTraceSwitch.Sw.TraceError )
					Trace.WriteLine( string.Format(CultureInfo.InvariantCulture,"[E]CRMWrapper4 CreateFromDynEntity SchemaName: {0}, ex: {1}", dynEnt.SchemaName,ex),CRMDynTraceSwitch.Sw.Info);
				throw;
			}
			dynEnt.EntityID                     =   created.id;
			if ( CRMDynTraceSwitch.Sw.TraceVerbose )
				Trace.WriteLine( string.Format(CultureInfo.InvariantCulture,"[V]CRMWrapper4 CreateFromDynEntity created SchemaName: {0}, id: {1}",dynEnt.SchemaName, dynEnt.EntityID),CRMDynTraceSwitch.Sw.Info);
			return dynEnt.EntityID;
		}

		public override InternalActivityParty CreateActivityParty(ADNDynActivityParty edyn)
		{
			return new InternalActivityParty(CreateActivityPartyRaw(edyn));
		}
		
		public activityparty CreateActivityPartyRaw(ADNDynActivityParty edyn)
		{
				activityparty ap        =   new activityparty();
				ap.addressused          =   edyn.addressused;
				ap.partyid              =   CrmTypes.CreateLookup(edyn.partyType, edyn.partyid);
				if (edyn.ContainsKey(CrmStr.scheduledend))
					ap.scheduledend     =   CrmTypes.CreateCrmDateTime(edyn.scheduledend);
				if (edyn.ContainsKey(CrmStr.scheduledstart))
					ap.scheduledstart   =   CrmTypes.CreateCrmDateTime(edyn.scheduledstart);
				if (edyn.ContainsKey(CrmStr.participationtypemask))
					ap.participationtypemask = CrmTypes.CreatePicklist(edyn.participationtypemask);
				if (edyn.ContainsKey(CrmStr.donotemail))
					ap.donotemail       =   CrmTypes.CreateCrmBoolean(edyn.donotemail);
				if (edyn.ContainsKey(CrmStr.donotfax))
					ap.donotfax         =   CrmTypes.CreateCrmBoolean(edyn.donotfax);
				if (edyn.ContainsKey(CrmStr.donotphone))
					ap.donotphone       =   CrmTypes.CreateCrmBoolean(edyn.donotphone);
				if (edyn.ContainsKey(CrmStr.donotpostalmail))
					ap.donotpostalmail  =   CrmTypes.CreateCrmBoolean(edyn.donotpostalmail);
				if (edyn.ContainsKey(CrmStr.effort))
					ap.effort           =   CrmTypes.CreateCrmFloat(edyn.effort);
				if (edyn.ContainsKey(CrmStr.resourcespecid))
					ap.resourcespecid   =   CrmTypes.CreateLookup(CrmStr.resourcespec, edyn.resourcespecid);
				return ap;
			}

		/// <summary>
		/// Update a dynamic entity
		/// </summary>
		public override void UpdateFromDynEntity(DynEntity dynEnt,bool isAdmin)
		{
			if ( CRMDynTraceSwitch.Sw.TraceVerbose )
				Trace.WriteLine( string.Format(CultureInfo.InvariantCulture,"[V]CRMWrapper4 UpdateFromDynEntity BEG SchemaName: {0}, isAdmin: {1}", dynEnt.SchemaName,isAdmin),CRMDynTraceSwitch.Sw.Info);
			// Check : we need PrimaryKey
			Guid CrmId                      =   dynEnt.PrimaryKeyGuidValue;
			// in case not here try to find it in EntityID-> if somebody just created a dynEntity with Ctor for update
			if ( (CrmId == Guid.Empty ) && (dynEnt.EntityID != Guid.Empty) )
			{
				dynEnt.PrimaryKeyGuidValue =    dynEnt.EntityID;
				CrmId                      =    dynEnt.EntityID;
			}
			if (CrmId == Guid.Empty)
			{
				string msg  =   string.Format("[V]CRMWrapper4 UpdateFromDynEntity No PrimaryKey Name: {0}", dynEnt.SchemaName);
				if ( CRMDynTraceSwitch.Sw.TraceError )
						Trace.WriteLine( msg,CRMDynTraceSwitch.Sw.Info);
				throw new Exception(msg);
			}

			DynamicEntity dEntity           =   new DynamicEntity();
			// Set the name of the entity type.
			dEntity.Name                    =   dynEnt.SchemaName;

			EntityConfig Tconfig            =   new EntityConfig(this,dynEnt.SchemaName);

			// Set the name of the entity type.
			dEntity.Name                    =   dynEnt.SchemaName;

			// Set the properties of the new DynamicEntity.
			List<Property> Lst              =   new List<Property>();
			foreach (KeyValuePair<string, InternalProperty> kvp in dynEnt.dicProperty)
			{
				Property p                  =   (Property)kvp.Value.Content;
				if (!Tconfig.attributesDic.ContainsKey(p.Name))
				{
					if ( CRMDynTraceSwitch.Sw.TraceVerbose )
						Trace.WriteLine( string.Format(CultureInfo.InvariantCulture,"[V]CRMWrapper4 UpdateFromDynEntity Property not in V4 Name: {0}", p.Name),CRMDynTraceSwitch.Sw.Info);
					continue;
				}
				if ( !p.Name.Equals(dynEnt.PrimaryKeyName) &&
						!Util4.ExtractAttributeFieldAsBool(Tconfig[p.Name], InternalAttributeFields.ValidForUpdate))
				{
					if ( CRMDynTraceSwitch.Sw.TraceVerbose )
						Trace.WriteLine( string.Format(CultureInfo.InvariantCulture,"[V]CRMWrapper4 UpdateFromDynEntity Property Not valid for update Name: {0}", p.Name),CRMDynTraceSwitch.Sw.Info);
					continue;
				}
				Lst.Add(p);
				if ( CRMDynTraceSwitch.Sw.TraceVerbose )
					Trace.WriteLine( string.Format(CultureInfo.InvariantCulture,"[V]CRMWrapper4 UpdateFromDynEntity adding key: {0}, value: {1}", kvp.Key, p),CRMDynTraceSwitch.Sw.Info);
			}
			dEntity.Properties              =   new Property[Lst.Count];
			int i                           =   0;
			foreach(Property p in Lst)
				dEntity.Properties[i++]     =   p;

			// Create the target.
			TargetUpdateDynamic target      =   new TargetUpdateDynamic();
			target.Entity                   =   dEntity;
			// Create the request object.
			UpdateRequest upd               =   new UpdateRequest();

			// Set the properties of the request object.
			upd.Target                      =   target;

			// Execute the request
			UpdateResponse  updated         =   null;
			try
			{
			if (isAdmin)
				updated                     =   (UpdateResponse)adminExecuteRaw(upd);
			else
				updated                     =   (UpdateResponse)userExecuteRaw(upd);
			}
			catch(Exception ex)
			{
				if ( CRMDynTraceSwitch.Sw.TraceError )
					Trace.WriteLine( string.Format(CultureInfo.InvariantCulture,"[E]CRMWrapper4 UpdateFromDynEntity SchemaName: {0}, ex: {1}", dynEnt.SchemaName,ex),CRMDynTraceSwitch.Sw.Info);
				throw;
			}
			if ( CRMDynTraceSwitch.Sw.TraceVerbose )
				Trace.WriteLine( string.Format(CultureInfo.InvariantCulture,"[V]CRMWrapper4 UpdateFromDynEntity END updated Name: {0}", dynEnt.SchemaName),CRMDynTraceSwitch.Sw.Info);
		}

		/// <summary>
		/// Delete a dynamic entity
		/// </summary>
		public override void DeleteFromDynEntity(DynEntity dynEnt,bool isAdmin)
		{
			if ( CRMDynTraceSwitch.Sw.TraceVerbose )
				Trace.WriteLine( string.Format(CultureInfo.InvariantCulture,"[V]CRMWrapper4 DeleteFromDynEntity BEG SchemaName: {0}, isAdmin: {1}", dynEnt.SchemaName,isAdmin),CRMDynTraceSwitch.Sw.Info);

			// Create the target.
			TargetDeleteDynamic target      =     new TargetDeleteDynamic();
			target.EntityId                 =     dynEnt.EntityID;
			target.EntityName               =     dynEnt.SchemaName;
			// Create the request object.
			DeleteRequest upd               =       new DeleteRequest();

			// Set the properties of the request object.
			upd.Target                      =   target;

			// Execute the request
			DeleteResponse  updated         =   null;
			try
			{
				if (isAdmin)
					updated                 =   (DeleteResponse)adminExecuteRaw(upd);
				else
					updated                 =   (DeleteResponse)userExecuteRaw(upd);
			}
			catch(Exception ex)
			{
				if ( CRMDynTraceSwitch.Sw.TraceError )
					Trace.WriteLine( string.Format(CultureInfo.InvariantCulture,"[E]CRMWrapper4 DeleteFromDynEntity SchemaName: {0}, ex: {1}", dynEnt.SchemaName,ex),CRMDynTraceSwitch.Sw.Info);
				throw;
			}
			if ( CRMDynTraceSwitch.Sw.TraceVerbose )
				Trace.WriteLine( string.Format(CultureInfo.InvariantCulture,"[V]CRMWrapper4 DeleteFromDynEntity END deleted SchemaName: {0}", dynEnt.SchemaName),CRMDynTraceSwitch.Sw.Info);
		}

		public override bool RetrieveFromDynEntity(DynEntity dynEnt,bool isAdmin)
		{
			if ( CRMDynTraceSwitch.Sw.TraceVerbose )
				Trace.WriteLine( string.Format(CultureInfo.InvariantCulture,"[V]CRMWrapper4 RetrieveFromDynEntity SchemaName: {0}, EntityID: {1}", dynEnt.SchemaName,dynEnt.EntityID),CRMDynTraceSwitch.Sw.Info);
			TargetRetrieveDynamic targetRetrieve    =   new TargetRetrieveDynamic();

			// Set the properties of the target.
			targetRetrieve.EntityName               =   dynEnt.SchemaName;
			if ( dynEnt.EntityID != Guid.Empty )
					targetRetrieve.EntityId         =   dynEnt.EntityID;// fast
			 else targetRetrieve.EntityId           =   dynEnt.PrimaryKeyGuidValue; //slow if real dynEntity

			// Create the request object.
			RetrieveRequest retrieve                =   new RetrieveRequest();

			// Set the properties of the request object.
			retrieve.Target                         =   targetRetrieve;
			retrieve.ColumnSet                      =   new AllColumns();

			// Indicate that the BusinessEntity should be retrieved as a DynamicEntity.
			retrieve.ReturnDynamicEntities          =   true;
			// Execute the request.
			RetrieveResponse retrieved              =   null;
			try
			{
				if (isAdmin)
					retrieved                       =   (RetrieveResponse)adminExecuteRaw(retrieve);
				else
					retrieved                       =   (RetrieveResponse)userExecuteRaw(retrieve);
			}
			catch (Exception ex)
			{
				if ( CRMDynTraceSwitch.Sw.TraceError )
					Trace.WriteLine( string.Format(CultureInfo.InvariantCulture,"[E]CRMWrapper4 RetrieveFromDynEntity Guid: {0}, ex: {1}", dynEnt.EntityID, ex),CRMDynTraceSwitch.Sw.Info);
				return false;
			}
			
			dynEnt.dicProperty.Clear();
			
			// Extract the DynamicEntity from the request.
			DynamicEntity entity                    =   (DynamicEntity)retrieved.BusinessEntity;

			// Extract properties from the dynamic entity
			foreach (Property ep in entity.Properties)
			{
				dynEnt.dicProperty.Add(ep.Name, new InternalProperty(ep));
				if ( CRMDynTraceSwitch.Sw.TraceVerbose )
					Trace.WriteLine( string.Format(CultureInfo.InvariantCulture,"[V]CRMWrapper4 RetrieveFromDynEntity Adding Property name: {0}", ep.Name),CRMDynTraceSwitch.Sw.Info);
			}
			if ( CRMDynTraceSwitch.Sw.TraceVerbose )
				Trace.WriteLine( "[V]CRMWrapper4 RetrieveFromDynEntity END.",CRMDynTraceSwitch.Sw.Info);
			return true;
		}

		public override bool RetrieveFromDynEntity(DynEntity dynEnt,InternalColumnSet cols,bool isAdmin)
		{
			if ( CRMDynTraceSwitch.Sw.TraceVerbose )
				Trace.WriteLine( string.Format(CultureInfo.InvariantCulture,"[V]CRMWrapper4 RetrieveFromDynEntity SchemaName: {0}, EntityID: {1}, cols.length: {2}.",
					dynEnt.SchemaName,dynEnt.EntityID, (cols == null ) ? 0:cols.Attributes.Length),CRMDynTraceSwitch.Sw.Info);
			TargetRetrieveDynamic targetRetrieve    =   new TargetRetrieveDynamic();

			// Set the properties of the target.
			targetRetrieve.EntityName               =   dynEnt.SchemaName;
			if ( dynEnt.EntityID != Guid.Empty )
					targetRetrieve.EntityId         =   dynEnt.EntityID;// fast
			 else targetRetrieve.EntityId           =   dynEnt.PrimaryKeyGuidValue; //slow if real dynEntity

			// Create the request object.
			RetrieveRequest retrieve                =   new RetrieveRequest();

			// Set the properties of the request object.
			retrieve.Target                         =   targetRetrieve;
			retrieve.ColumnSet                      =   (cols == null) ? (ColumnSetBase)(new AllColumns()):(ColumnSetBase)(ColumnSet)cols;

			// Indicate that the BusinessEntity should be retrieved as a DynamicEntity.
			retrieve.ReturnDynamicEntities          =   true;
			// Execute the request.
			RetrieveResponse retrieved              =   null;
			try
			{
				if (isAdmin)
					retrieved                       =   (RetrieveResponse)adminExecuteRaw(retrieve);
				else
					retrieved                       =   (RetrieveResponse)userExecuteRaw(retrieve);
			}
			catch (Exception ex)
			{
				if ( CRMDynTraceSwitch.Sw.TraceError )
					Trace.WriteLine( string.Format(CultureInfo.InvariantCulture,"[E]CRMWrapper4 RetrieveFromDynEntity Guid: {0}, ex: {1}", dynEnt.EntityID, ex),CRMDynTraceSwitch.Sw.Info);
				return false;
			}
			
			dynEnt.dicProperty.Clear();
			
			// Extract the DynamicEntity from the request.
			DynamicEntity entity                    =   (DynamicEntity)retrieved.BusinessEntity;

			// Extract properties from the dynamic entity
			foreach (Property ep in entity.Properties)
			{
				dynEnt.dicProperty.Add(ep.Name, new InternalProperty(ep));
				if ( CRMDynTraceSwitch.Sw.TraceVerbose )
					Trace.WriteLine( string.Format(CultureInfo.InvariantCulture,"[V]CRMWrapper4 RetrieveFromDynEntity Adding Property name: {0}", ep.Name),CRMDynTraceSwitch.Sw.Info);
			}
			if ( CRMDynTraceSwitch.Sw.TraceVerbose )
				Trace.WriteLine( "[V]CRMWrapper4 RetrieveFromDynEntity END.",CRMDynTraceSwitch.Sw.Info);
			return true;
		}

		public override void AssignFromDynEntity(DynEntity dynEnt,Guid wUserId, bool isAdmin)
		{
			SecurityPrincipal assignee  =   new SecurityPrincipal();
			// Set the properties of the SecurityPrincipal object.'
			// PrincipalId is a GUID that identifies the user or team 
			// that will own this record.
			assignee.PrincipalId        =   wUserId;

			TargetOwnedDynamic target   =   new TargetOwnedDynamic();
			target.EntityName           =   dynEnt.SchemaName;
			target.EntityId             =   dynEnt.EntityID;

			// Create the request object.
			AssignRequest assign        =   new AssignRequest();

			// Set the properties of the request object.'
			assign.Assignee             =   assignee;
			assign.Target               =   target;

			// Execute the request.
			AssignResponse assignResponse = null;
			try
			{
				if (isAdmin)
					assignResponse = (AssignResponse)adminExecuteRaw(assign);
				else
					assignResponse = (AssignResponse)userExecuteRaw(assign);
			}
			catch (Exception ex)
			{
				if ( CRMDynTraceSwitch.Sw.TraceError )
					Trace.WriteLine( string.Format(CultureInfo.InvariantCulture,"[E]CRMWrapper4Assign EntityName: {0}, EntityID : {1},UserId : {2}, isAdmin: {3}, ex: {4}",
						new object[] { dynEnt.SchemaName, dynEnt.EntityID, userId, isAdmin, ex }),CRMDynTraceSwitch.Sw.Info);
				throw;
			}
		}

		public override string GetEntityName(InternalDynamicEntity dEntity)
		{
			return ((DynamicEntity)dEntity.Content).Name;
		}
		
		#region CRM properties worker methods

		/// <summary>
		/// Helper method to add a string as a StringProperty: creates the property, initializes its key and content, add it tointernal dic.
		/// </summary>
		public override StringInternalProperty AddStringProperty(string key, string val,DicProperties dic)
		{
			StringProperty sprop            =   new StringProperty();
			StringInternalProperty reslt    =   new StringInternalProperty(sprop);
			dic[key]                        =   reslt;
			sprop.Name                      =   key;
			sprop.Value                     =   val;
			return reslt;
		}

		public override CrmBooleanInternalProperty AddBooleanProperty(string key, Boolean val,DicProperties dic)
		{
			CrmBooleanProperty test             =   new CrmBooleanProperty();
			CrmBooleanInternalProperty reslt    =   new CrmBooleanInternalProperty (test);
			dic[key]                            =   reslt;
			test.Name                           =   key;
			test.Value                          =   CrmTypes.CreateCrmBoolean(val);
			test.Value.Value                    =   val;
			return reslt;
		}

		public override CrmDateTimeInternalProperty AddDateTimeProperty(string name, string value,DicProperties dic)
		{
			CrmDateTimeProperty result          =   new CrmDateTimeProperty();
			CrmDateTimeInternalProperty reslt   =   new CrmDateTimeInternalProperty (result);
			dic[name]                           =   reslt;
			result.Name                         =   name;
			result.Value                        =   CrmTypes.CreateCrmDateTime(value);
			return reslt;
		}


		public override CrmDecimalInternalProperty AddDecimalProperty(string name, Decimal value,DicProperties dic)
		{
			CrmDecimalProperty result           =   new CrmDecimalProperty();
			CrmDecimalInternalProperty reslt    =   new CrmDecimalInternalProperty (result);
			dic[name]                           =   reslt;
			result.Name                         =   name;
			result.Value                        =   CrmTypes.CreateCrmDecimal(value);
			return reslt;
		}

		public override CrmFloatInternalProperty AddFloatProperty(string name, double value,DicProperties dic)
		{
			CrmFloatProperty result             =   new CrmFloatProperty();
			CrmFloatInternalProperty reslt      =   new CrmFloatInternalProperty (result);
			dic[name]                           =   reslt;
			result.Name                         =   name;
			result.Value                        =   CrmTypes.CreateCrmFloat(value);
			return reslt;
		}

		public override CrmFloatInternalProperty AddFloatProperty(string name, float value,DicProperties dic)
		{
			CrmFloatProperty result             =   new CrmFloatProperty();
			CrmFloatInternalProperty reslt      =   new CrmFloatInternalProperty (result);
			dic[name]                           =   reslt;
			result.Name                         =   name;
			result.Value                        =   CrmTypes.CreateCrmFloat(value);
			return reslt;
		}

		public override CrmMoneyInternalProperty AddMoneyProperty(string name, Decimal value,DicProperties dic)
		{
			CrmMoneyProperty result             =   new CrmMoneyProperty();
			CrmMoneyInternalProperty reslt      =   new CrmMoneyInternalProperty (result);
			dic[name]                           =   reslt;
			result.Name                         =   name;
			result.Value                        =   CrmTypes.CreateCrmMoney(value);
			return reslt;
		}

		public override CrmNumberInternalProperty AddNumberProperty(string name, int value,DicProperties dic)
		{
			CrmNumberProperty result            =   new CrmNumberProperty();
			CrmNumberInternalProperty reslt     =   new CrmNumberInternalProperty (result);
			dic[name]                           =   reslt;
			result.Name                         =   name;
			result.Value                        =   CrmTypes.CreateCrmNumber(value);
			return reslt;
		}

		public override CustomerInternalProperty AddCustomerProperty(string name, string type, Guid value,DicProperties dic)
		{
			CustomerProperty result             =   new CustomerProperty();
			CustomerInternalProperty reslt      =   new CustomerInternalProperty (result);
			dic[name]                           =   reslt;
			result.Name                         =   name;
			result.Value                        =   CrmTypes.CreateCustomer(type, value);
			return reslt;
		}

		public override DynamicEntityArrayInternalProperty AddDynamicEntityArrayProperty(string name, InternalDynamicEntityArray value,DicProperties dic)
		{
			DynamicEntityArrayProperty result           =   new DynamicEntityArrayProperty();
			DynamicEntityArrayInternalProperty reslt    =   new DynamicEntityArrayInternalProperty (result);
			dic[name]                                   =   reslt;
			result.Name                                 =   name;
			result.Value                                =   (CRM4Server.DynamicEntity[])value.Content;
			return reslt;
		}

		public override EntityNameReferenceInternalProperty AddEntityNameReferenceProperty(string name, string value,DicProperties dic)
		{
			EntityNameReferenceProperty result          =   new EntityNameReferenceProperty();
			EntityNameReferenceInternalProperty reslt   =   new EntityNameReferenceInternalProperty (result);
			dic[name]                                   =   reslt;
			result.Name                                 =   name;
			result.Value                                =   CrmTypes.CreateEntityNameReference(value);
			return reslt;
		}

		public override KeyInternalProperty AddKeyProperty(string name, Guid value,DicProperties dic)
		{
			KeyProperty result                          =   new KeyProperty();
			KeyInternalProperty reslt                   =   new KeyInternalProperty (result);
			dic[name]                                   =   reslt;
			result.Name                                 =   name;
			result.Value                                =   CrmTypes.CreateKey(value);
			return reslt;
		}

		public override LookupInternalProperty AddLookupProperty(string name, String type, Guid value,DicProperties dic)
		{
			LookupProperty result               =   new LookupProperty();
			LookupInternalProperty reslt        =   new LookupInternalProperty (result);
			dic[name]                           =   reslt;
			result.Name                         =   name;
			result.Value                        =   CrmTypes.CreateLookup(type, value);
			return reslt;
		}

		public override CalendarRulesInternalProperty AddCalendarRulesProperty(string name,object value,DicProperties dic)
		{
			CalendarRulesInternalProperty reslt =   new CalendarRulesInternalProperty(value);
			dic[name]                           =   reslt;
			return reslt;
		}

		public override OwnerInternalProperty AddOwnerProperty(string name, String type, Guid value,DicProperties dic)
		{
			OwnerProperty result                =   new OwnerProperty();
			OwnerInternalProperty reslt         =   new OwnerInternalProperty (result);
			dic[name]                           =   reslt;
			result.Name                         =   name;
			result.Value                        =   CrmTypes.CreateOwner(type, value);
			return reslt;
		}

		public override PicklistInternalProperty AddPicklistProperty(string name, int value,DicProperties dic)
		{
			PicklistProperty result             =   new PicklistProperty();
			PicklistInternalProperty reslt      =   new PicklistInternalProperty (result);
			dic[name]                           =   reslt;
			result.Name                         =   name;
			result.Value                        =   CrmTypes.CreatePicklist(value);
			return reslt;
		}

		public override StateInternalProperty AddStateProperty(string name, String value,DicProperties dic)
		{
			StateProperty result                =   new StateProperty();
			StateInternalProperty reslt         =   new StateInternalProperty (result);
			dic[name]                           =   reslt;
			result.Name                         =   name;
			result.Value                        =   value;
			return reslt;
		}

		public override StatusInternalProperty AddStatusProperty(string name, int value,DicProperties dic)
		{
			StatusProperty result = new StatusProperty();
			StatusInternalProperty reslt =   new StatusInternalProperty (result);
			dic[name] = reslt;
			result.Name = name;
			result.Value = CrmTypes.CreateStatus(value);
			return reslt;
		}

		public override UniqueIdentifierInternalProperty AddUniqueIdentifierProperty(string name, Guid value,DicProperties dic)
		{
			UniqueIdentifierProperty result = new UniqueIdentifierProperty();
			UniqueIdentifierInternalProperty reslt   =   new UniqueIdentifierInternalProperty (result);
			dic[name] = reslt;
			result.Name = name;
			result.Value = CrmTypes.CreateUniqueIdentifier(value);
			return reslt;
		}

		#endregion CRM properties worker methods

		#region Extracting values

		/// <summary>
		/// Beware that when a string value is string.empty, CRM server web services doesn't return the corresponding property
		/// This is a bad conception and to live with this, we must return string.Empywhen the value is not found.
		/// This could also mean that the attribut is not present....
		/// </summary>
		public override string StringPropertyValue(string key,DicProperties dic)
		{
			if ( dic.ContainsKey(key) )
				return ((StringProperty)dic[key].Content).Value;
			return string.Empty;
		}

		public override bool IsBooleanPropertyValueNull(string key,DicProperties dic)
		{
			return ((CrmBooleanProperty )dic[key].Content).Value.IsNull;
		}
		public override bool BooleanPropertyValue(string key,DicProperties dic)
		{
			return ((CrmBooleanProperty )dic[key].Content).Value.Value;
		}

		public override string DateTimePropertyValue(string key,DicProperties dic)
		{
			return ((CrmDateTimeProperty)dic[key].Content).Value.Value;
		}
		public override DateTime DateTimePropertyDate(string key,DicProperties dic,bool toUserTime)
		{
			Property p      =   (Property)dic[key].Content;
			if (p != null && !((CrmDateTimeProperty)p).Value.IsNull )
				return CRMUtil.ConvertDateFromCrm(((CrmDateTimeProperty)p).Value.Value,toUserTime);
			return CRMUtil.minDateTime;
		}

		public override bool IsDecimalPropertyValueNull(string key,DicProperties dic)
		{
			return ((CrmDecimalProperty)dic[key].Content).Value.IsNull;
		}
		public override decimal DecimalPropertyValue(string key,DicProperties dic)
		{
			return ((CrmDecimalProperty)dic[key].Content).Value.Value;
		}

		public override bool IsFloatPropertyValueNull(string key,DicProperties dic)
		{
			return ((CrmFloatProperty )dic[key].Content).Value.IsNull;
		}
		
		[Obsolete("Use DoublePropertyValue")]
		public override float FloatPropertyValue(string key,DicProperties dic)
		{
			return (float)((CrmFloatProperty )dic[key].Content).Value.Value;
		}
		
		public override double DoublePropertyValue(string key,DicProperties dic)
		{
			return ((CrmFloatProperty )dic[key].Content).Value.Value;
		}
		
		public override bool IsMoneyPropertyValueNull(string key,DicProperties dic)
		{
			return ((CrmMoneyProperty )dic[key].Content).Value.IsNull;
		}
		public override decimal MoneyPropertyValue(string key,DicProperties dic)
		{
			return ((CrmMoneyProperty )dic[key].Content).Value.Value;
		}

		public override bool IsNumberPropertyValueNull(string key,DicProperties dic)
		{
			return ((CrmNumberProperty)dic[key].Content).Value.IsNull;
		}
		public override int NumberPropertyValue(string key,DicProperties dic)
		{
			return ((CrmNumberProperty)dic[key].Content).Value.Value;
		}
		public override bool IsUniqueIdentifierPropertyValueNull(string key,DicProperties dic)
		{
			return ((UniqueIdentifierProperty)dic[key].Content).Value.IsNull;
		}
		public override Guid UniqueIdentifierPropertyValue(string key,DicProperties dic)
		{
			return ((UniqueIdentifierProperty)dic[key].Content).Value.Value;
		}
		public override bool IsPicklistPropertyIntValueNull(string key,DicProperties dic)
		{
			return ((PicklistProperty)dic[key].Content).Value.IsNull;
		}
		public override int PicklistPropertyIntValue(string key,DicProperties dic)
		{
			return ((PicklistProperty)dic[key].Content).Value.Value;
		}
		public override string PicklistPropertyNameValue(string key,DicProperties dic)
		{
			return ((PicklistProperty)dic[key].Content).Name;
		}
		
		public override string EntityNameReferencePropertyValue(string key,DicProperties dic)
		{
			return ((EntityNameReferenceProperty)dic[key].Content).Value.Value;
		}

		public override Guid KeyPropertyValue(string key,DicProperties dic)
		{
			if ( dic[key].Content is KeyProperty ) 
				return ((KeyProperty)dic[key].Content).Value.Value;
			if ( dic[key].Content is LookupProperty ) 
				return ((LookupProperty)dic[key].Content).Value.Value;
			return Guid.Empty;
		}

		public override bool  IsLookupPropertyValueNull(string key,DicProperties dic)
		{
			return ((LookupProperty )dic[key].Content).Value.IsNull;
		}
		public override string LookupPropertyType(string key,DicProperties dic)
		{
			return ((LookupProperty )dic[key].Content).Value.type;
		}
		public override string LookupPropertyName(string key,DicProperties dic)
		{
			return ((LookupProperty )dic[key].Content).Value.name;
		}
		public override Guid LookupPropertyValue(string key,DicProperties dic)
		{
			return ((LookupProperty )dic[key].Content).Value.Value;
		}

		public override object CalendarRulesPropertyValue(string key,DicProperties dic)
		{
			return ((calendarrule[])dic[key].Content);
		}
		
		public override int CalendarRulesPropertyLength(string key,DicProperties dic)
		{
			return ((calendarrule[])dic[key].Content).Length;
		}
		
		public override object CalendarRulesPropertyAtIndex(string key,DicProperties dic,int idx)
		{
			calendarrule[] cr   =   (calendarrule[])dic[key].Content;
			if ( ( cr != null ) && (idx < cr.Length ) )
				return cr[idx];
			return null;
		}

		public override Guid CalendarRulesPropertyLookupAtIndex(string key,DicProperties dic,int idx)
		{
			calendarrule[] cr   =   (calendarrule[])dic[key].Content;
			if ( ( cr != null ) && (idx < cr.Length ) )
				return cr[idx].calendarruleid.Value;
			return Guid.Empty;
		}

		public override bool IsOwnerPropertyValueNull(string key,DicProperties dic)
		{
			return ((OwnerProperty )dic[key].Content).Value.IsNull;
		}
		public override Guid OwnerPropertyValue(string key,DicProperties dic)
		{
			return ((OwnerProperty )dic[key].Content).Value.Value;
		}
		public override string OwnerPropertyName(string key,DicProperties dic)
		{
			return ((OwnerProperty)dic[key].Content).Value.name;
		}
		public override string OwnerPropertyType(string key,DicProperties dic)
		{
			return ((OwnerProperty)dic[key].Content).Value.type;
		}
		public override bool IsCustomerPropertyValueNull(string key,DicProperties dic)
		{
			return ((CustomerProperty)dic[key].Content).Value.IsNull;
		}
		public override Guid CustomerPropertyValue(string key,DicProperties dic)
		{
			return ((CustomerProperty)dic[key].Content).Value.Value;
		}
		public override string CustomerPropertyName(string key,DicProperties dic)
		{
			return ((CustomerProperty)dic[key].Content).Value.name;
		}
		public override string CustomerPropertyType(string key,DicProperties dic)
		{
			return ((CustomerProperty)dic[key].Content).Value.type;
		}
		public override InternalDynamicEntityArray DynamicEntityArrayProperty(String key,DicProperties dic)
		{
			if ( dic.ContainsKey(key) )
				return new InternalDynamicEntityArray(((DynamicEntityArrayProperty)dic[key].Content).Value);
			return null;
		}
		public override string StatePropertyValue(string key,DicProperties dic)
		{
			return ((StateProperty)dic[key].Content).Value;
		}

		public override string IncidentStatePropertyValue(string key,DicProperties dic)
		{
			return ((StateProperty)dic[key].Content).Value;
		}

		public override string StatePropertyNameValue(string key,DicProperties dic)
		{
			return ((StateProperty)dic[key].Content).Name;
		}
		public override int StatusPropertyIntValue(string key,DicProperties dic)
		{
			return ((StatusProperty)dic[key].Content).Value.Value;
		}
		public override string StatusPropertyNameValue(string key,DicProperties dic)
		{
			return ((StatusProperty)dic[key].Content).Value.name;
		}

		#endregion Extracting values

		#endregion special for DynEntity

		#region used by EntityList

		public override List<string> GetEntityList()
		{
			List<string> entLst     =   new List<string>();
			entLst.Insert(0,"uomschedule");
			entLst.Insert(0,"uom");
			entLst.Insert(0,"territory");
			entLst.Insert(0,"template");
			entLst.Insert(0,"team");
			entLst.Insert(0,"task");
			entLst.Insert(0,"systemuser");
			entLst.Insert(0,"subject");
			entLst.Insert(0,"site");
			entLst.Insert(0,"serviceappointment");
			entLst.Insert(0,"service");
			entLst.Insert(0,"salesorderdetail");
			entLst.Insert(0,"salesorder");
			entLst.Insert(0,"salesliterature");
			entLst.Insert(0,"role");
			entLst.Insert(0,"resource");
			entLst.Insert(0,"report");
			entLst.Insert(0,"quotedetail");
			entLst.Insert(0,"quote");
			entLst.Insert(0,"product");
			entLst.Insert(0,"pricelevel");
			entLst.Insert(0,"phonecall");
			entLst.Insert(0,"opportunity");
			entLst.Insert(0,"list");
			entLst.Insert(0,"letter");
			entLst.Insert(0,"lead");
			entLst.Insert(0,"kbarticle");
			entLst.Insert(0,"invoicedetail");
			entLst.Insert(0,"invoice");
			entLst.Insert(0,"incident");
			entLst.Insert(0,"fax");
			entLst.Insert(0,"equipment");
			entLst.Insert(0,"email");
			entLst.Insert(0,"discount");
			entLst.Insert(0,"customeraddress");
			entLst.Insert(0,"contractdetail");
			entLst.Insert(0,"contract");
			entLst.Insert(0,"contact");
			entLst.Insert(0,"competitor");
			entLst.Insert(0,"campaignresponse");
			entLst.Insert(0,"campaign");
			entLst.Insert(0,"calendar");
			entLst.Insert(0,"businessunit");
			entLst.Insert(0,"appointment");
			entLst.Insert(0,"account");
			return entLst;
		}
		#endregion used by EntityList
	
		#region Serialize into XML and return the string
		
		public override string Serialize(DynEntity dyn)
		{
			if ( CRMTraceSwitch.Sw.TraceVerbose )
				Trace.WriteLine( string.Format(CultureInfo.InvariantCulture,"[V]CRMWrapper4 Serialize BEG dyn.schemaname: {0}", dyn.SchemaName),CRMTraceSwitch.Sw.Info);
			string xml                              =   string.Empty;
			try
			{
				StringBuilder sb                    =   new StringBuilder();
				DynamicEntity dEnt                  =   ToDynamicEntityRaw(dyn);
				
				XmlSerializer serializer = new XmlSerializer(typeof(DynamicEntity));

				// The using statement also closes the StreamWriter.
				using (StringWriter writer          =   new StringWriter(sb)) 
				{
				   serializer.Serialize(writer,dEnt);
				}
				xml                                 =   sb.ToString();
			}
			catch(Exception ex) // not throwing in Ctor
			{
				Trace.WriteLine( string.Format(CultureInfo.InvariantCulture,"[E]CRMWrapper4 Deserialize<T> ex: {0}",ex),CRMTraceSwitch.Sw.Info);
				throw;
			}
			if ( CRMTraceSwitch.Sw.TraceVerbose )
				Trace.WriteLine( string.Format(CultureInfo.InvariantCulture,"[V]CRMWrapper4 Serialize BEG dyn.schemaname: {0}", dyn.SchemaName),CRMTraceSwitch.Sw.Info);
			return xml;
		}

		#endregion

		#region Deserialize the CRM contact from XML

		public override T Deserialize<T>(ResetWrapperHandler fnr, string xml)
		{
			if ( CRMTraceSwitch.Sw.TraceVerbose )
				Trace.WriteLine( string.Format(CultureInfo.InvariantCulture,"[V]CRMWrapper4 Deserialize<T> BEG xml: {0}", xml),CRMTraceSwitch.Sw.Info);
			T dyn                             =   null;
			try
			{
				DynamicEntity dEnt          =   new DynamicEntity();
				XmlSerializer serializer    =   new XmlSerializer(typeof(DynamicEntity));
				using ( StringReader reader =   new StringReader(xml) )
				{
					// Deserialize the contact object.
					object tmp              =   serializer.Deserialize(reader);
					dEnt                    =   tmp as DynamicEntity;
				}
				dyn                         =   new T();
				dyn.InitTemplate(fnr,new InternalDynamicEntity(dEnt),null,null);
				dyn.EntityID                =   dyn.PrimaryKeyGuidValue;
			}
			catch(Exception ex)
			{
				Trace.WriteLine( string.Format(CultureInfo.InvariantCulture,"[E]CRMWrapper4 Deserialize<T> ex: {0}",ex),CRMTraceSwitch.Sw.Info);
				throw;
			}
			if ( CRMTraceSwitch.Sw.TraceVerbose )
				Trace.WriteLine( string.Format(CultureInfo.InvariantCulture,"[V]CRMWrapper4 Deserialize<T> END SchemaName: {0}",dyn.SchemaName),CRMTraceSwitch.Sw.Info);
			return dyn;
		}

		#endregion Deserialize the CRM contact from XML

		#region InitializeFrom
			
		public override Guid InitializeFrom(DynEntity dyn,string targetEntity,bool isAdmin)
		{
			if ( CRMTraceSwitch.Sw.TraceVerbose )
				Trace.WriteLine( string.Format(CultureInfo.InvariantCulture,"[V]CRMWrapper4 InitializeFrom BEG SchemaName: {0}, targetEntity: {1}",dyn.SchemaName,targetEntity),CRMTraceSwitch.Sw.Info);
			Guid createdId              =   Guid.Empty;
			try
			{
				InitializeFromRequest req   =   new InitializeFromRequest();
				req.ReturnDynamicEntities   =   true;
				req.TargetEntityName        =   targetEntity;
				req.TargetFieldType         =   CRM4Server.TargetFieldType.ValidForCreate;
				req.EntityMoniker           =   new Moniker();
				req.EntityMoniker.Id        =   dyn.PrimaryKeyGuidValue;
				req.EntityMoniker.Name      =   dyn.SchemaName;

				InitializeFromResponse resp = null;
				if (isAdmin)
						resp                =   (InitializeFromResponse) adminService4.ExecuteRaw(req);
				else    resp                =   (InitializeFromResponse) userService4.ExecuteRaw(req);
				if (isAdmin)
						createdId           =   adminService4.CreateRaw(resp.Entity);
				else    createdId           =   userService4.CreateRaw(resp.Entity);
			}
			catch (SoapException sx)
			{
				string msg  =   string.Format(CultureInfo.InvariantCulture,"[E]CRMWrapper4 InitializeFrom ex: {0}-{1}", sx, sx.Detail.InnerText);
				if ( CRMTraceSwitch.Sw.TraceError )
					Trace.WriteLine(msg ,CRMTraceSwitch.Sw.Info);
				throw new CRMWrapperException(msg, sx);
			}
			catch(Exception ex)
			{
				Trace.WriteLine( string.Format(CultureInfo.InvariantCulture,"[E]CRMWrapper4 InitializeFrom ex: {0}",ex),CRMTraceSwitch.Sw.Info);
				throw;
			}
			if ( CRMTraceSwitch.Sw.TraceVerbose )
				Trace.WriteLine( string.Format(CultureInfo.InvariantCulture,"[V]CRMWrapper4 InitializeFrom END createdId: {0}",createdId),CRMTraceSwitch.Sw.Info);
			return createdId;
		}
		
		#endregion InitializeFrom

	}
}

